diff --git a/.codex/skills/clava-scripting/SKILL.md b/.codex/skills/clava-scripting/SKILL.md new file mode 100644 index 0000000000..c6353222e1 --- /dev/null +++ b/.codex/skills/clava-scripting/SKILL.md @@ -0,0 +1,39 @@ +--- +name: clava-scripting +description: Create, update, and explain Clava/LARA scripts in TypeScript using Clava-JS and Lara-JS APIs, including Query/Selector usage, joinpoint selection and filters, and AST transformations. Use for Clava script authoring, joinpoint queries, or refactoring code via Clava/Lara weaver APIs. +--- + +# Clava Scripting + +## Overview + +Write and modify Clava scripts in TypeScript using Clava/Lara APIs for joinpoint selection and AST transformations. + +## Quick Start + +Use ESM imports with `.js` extensions, select joinpoints with `Query`, and transform with Clava APIs. + +```ts +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { FunctionJp } from "@specs-feup/clava/api/Joinpoints.ts"; + +const $fn = Query.search(FunctionJp, { isImplementation: true }).first(); +if ($fn) $fn.clone(`${$fn.name}_clone`); +``` + +## Workflow + +1. Identify joinpoints and attributes. +Use the generated joinpoint wrappers in `@specs-feup/clava/api/Joinpoints.ts` and check `Joinpoints.ts` for default attributes and available fields. + +2. Select joinpoints with Query/Selector. +Use `Query.search`, `Query.searchFrom`, `Query.searchFromInclusive`, `Query.childrenFrom`, and `Selector.scope`. Filters accept strings, regex, predicate functions, or objects keyed by attributes. `Selector` is iterable and methods like `.get()`, `.first()`, and `.chain()` consume the current selection. + +3. Transform and emit code. +Use joinpoint methods like `.clone()`, `.replaceWith()`, `.addParam()`, `.setReturnType()`, and factories in `ClavaJoinPoints` for new nodes. Use `Query.root().code` or `Clava.writeCode()` to inspect or emit output. + +## References + +- `references/query-api.md` for Query/Selector behavior and filters. +- `references/clava-apis.md` for key Clava/Lara API entry points and file locations. +- `references/examples.md` for real scripts and test patterns. diff --git a/.codex/skills/clava-scripting/agents/openai.yaml b/.codex/skills/clava-scripting/agents/openai.yaml new file mode 100644 index 0000000000..1fbab5a6f5 --- /dev/null +++ b/.codex/skills/clava-scripting/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Clava Scripting" + short_description: "Write and edit Clava/Lara scripts" + default_prompt: "Use $clava-scripting to draft a Clava TypeScript script that queries joinpoints and applies a transformation." diff --git a/.codex/skills/clava-scripting/references/clava-apis.md b/.codex/skills/clava-scripting/references/clava-apis.md new file mode 100644 index 0000000000..9b9c0850c0 --- /dev/null +++ b/.codex/skills/clava-scripting/references/clava-apis.md @@ -0,0 +1,33 @@ +# Clava and Lara API Entry Points + +Use this to locate the right TypeScript APIs and understand where functionality lives. + +## Clava-JS APIs (this repo) + +- Joinpoint wrappers (generated): `Clava-JS/api/Joinpoints.ts` +- Joinpoint factories/utilities: `Clava-JS/api/clava/ClavaJoinPoints.ts` +- Core Clava utilities and AST stack: `Clava-JS/api/clava/Clava.ts` +- Common passes/opts built on Query: `Clava-JS/api/clava/opt`, `Clava-JS/api/clava/pass` + +Imports typically use: +- `@specs-feup/clava/api/Joinpoints.ts` +- `@specs-feup/clava/api/clava/ClavaJoinPoints.ts` +- `@specs-feup/clava/api/clava/Clava.ts` + +## Lara-JS APIs (sibling repo) + +- Query API: `../lara/Lara-JS/api/weaver/Query.ts` +- Selector behavior and filters: `../lara/Lara-JS/api/weaver/Selector.ts` +- Weaver utilities: `../lara/Lara-JS/api/weaver/Weaver.ts` + +If the Lara-JS repo is not a sibling of Clava, search for `Lara-JS/api/weaver/Query.ts`. + +Imports typically use: +- `@specs-feup/lara/api/weaver/Query.ts` +- `@specs-feup/lara/api/weaver/Weaver.ts` + +## Notes + +- Joinpoint wrappers expose attributes and methods specific to each type. +- `ClavaJoinPoints` provides factory helpers for types, statements, expressions, and declarations. +- Use `.code` on joinpoints (or `Query.root().code`) to inspect generated code quickly. diff --git a/.codex/skills/clava-scripting/references/examples.md b/.codex/skills/clava-scripting/references/examples.md new file mode 100644 index 0000000000..b57d102de1 --- /dev/null +++ b/.codex/skills/clava-scripting/references/examples.md @@ -0,0 +1,28 @@ +# Script Examples and Patterns + +Use these files for concrete patterns and idioms. + +## Weaver tests (JS, but patterns apply to TS) + +- `ClavaWeaver/resources/clava/test/weaver/Function2.js` + - Select function, clone it, change return type, replace body, add param. + +- `ClavaWeaver/resources/clava/test/weaver/Clone.js` + - Clone all functions with definitions and print file code. + +- `ClavaWeaver/resources/clava/test/weaver/Field.js` + - Navigate record fields and read attributes like `isPublic`. + +- `ClavaWeaver/resources/clava/test/issues/Issue168.js` + - Normalize loops and decompose statements using `NormalizeToSubset` and `StatementDecomposer`. + +- `ClavaWeaver/resources/clava/test/issues/Issue_aiq_1.js` + - Filter loops by kind, inspect condition relation. + +## API tests + +- `ClavaWeaver/resources/clava/test/api/ClavaJoinPointsTest.js` + - Large catalog of `ClavaJoinPoints` factory helpers. + +- `Clava-JS/api/Query.test.ts` + - Query chaining, `.scope()`, `.chain()`, and regex selection. diff --git a/.codex/skills/clava-scripting/references/query-api.md b/.codex/skills/clava-scripting/references/query-api.md new file mode 100644 index 0000000000..f78fd8caf2 --- /dev/null +++ b/.codex/skills/clava-scripting/references/query-api.md @@ -0,0 +1,47 @@ +# Query and Selector API + +Use this when writing or debugging joinpoint selection logic. + +## Primary sources + +- Query API: `../lara/Lara-JS/api/weaver/Query.ts` (sibling worktree) +- Selector behavior: `../lara/Lara-JS/api/weaver/Selector.ts` (sibling worktree) +- Query usage tests: `Clava-JS/api/Query.test.ts` + +If the Lara-JS repo is not a sibling of Clava, search for `Lara-JS/api/weaver/Query.ts`. + +## Core patterns + +- `Query.root()` returns the root joinpoint. +- `Query.search(Type, filter?, traversal?)` starts from root. +- `Query.searchFrom($base, Type?, filter?, traversal?)` searches below a base node (exclusive). +- `Query.searchFromInclusive($base, Type?, filter?, traversal?)` includes the base node. +- `Query.childrenFrom($base, Type?, filter?)` searches direct children. +- `Selector.scope(Type?, filter?)` searches inside the scope of the previously selected nodes. + +## Filters + +Filters accept: +- A string or regex applied to the default attribute for that joinpoint type. +- A predicate function `(jp) => boolean`. +- An object with attribute names as keys and values of string/regex/predicate. + +Default attributes are defined in the joinpoint wrappers and can be resolved via `Weaver.getDefaultAttribute()`. + +## Selector consumption + +`Selector` is iterable and is consumed by `for..of`, `.get()`, `.first()`, and `.chain()`. +Use `.chain()` when you need the full chain map (e.g., `loop`, `loop_0`, `loop_1`). + +## Minimal examples + +```ts +for (const $fn of Query.search(FunctionJp, { isImplementation: true })) { + // $fn is a joinpoint instance +} + +const chains = Query.search(FunctionJp, "query_loop") + .search(Loop) + .search(Loop) + .chain(); +``` diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 4c5139427c..0000000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,100 +0,0 @@ -# Copilot Instructions for the Clava Repository - -## Project Overview - -Clava is a modular source-to-source compiler for C, C++, CUDA, and OpenCL, supporting advanced code analysis and transformation. It is implemented using a combination of TypeScript/JavaScript (Node.js), Java, and C++. Clava is designed for composability and reusability, and integrates with the LARA DSL for custom code transformations. - -## Development Environment & Setup - -- **Node.js Version:** 20 or 22 (required for Clava-JS) -- **Java Version:** 17+ (required for Java components) -- **Build System:** Gradle for Java modules, npm for TypeScript/JavaScript -- **IDE:** VSCode is recommended for development - -## Architecture - -- **Frontend (C++):** - The `ClangAstDumper` component extracts AST information from Clang-based codebases. -- **Middle-end (Java):** - Components like `ClangAstParser` and `ClavaWeaver` process ASTs and apply transformations. -- **API Layer (TypeScript/JavaScript):** - The `Clava-JS` module provides the main user-facing API and runtime, exposing Clava's features to Node.js environments. -- **Build Integration:** - The `CMake` package enables integration with CMake-based build systems. - -### Related Projects -- **lara-framework**: Core framework providing weaver infrastructure and JavaScript APIs -- **specs-java-libs**: Java utility libraries used throughout the project - -## Key Directories - -- `Clava-JS/`: TypeScript/JavaScript API and runtime. -- `ClavaWeaver/`: Java-based weaving engine. -- `ClangAstDumper/`: C++ AST dumper using Clang. -- `ClangAstParser/`: Java AST parser. -- `ClavaAst/`, `ClavaHls/`, `ClavaLaraApi/`, `AntarexClavaApi/`: Supporting modules for AST, HLS, LARA API, and Antarex integration. -- `CMake/`: CMake integration scripts and utilities. -- `docs/`: Documentation, tutorials, and common issues. - -## Build and Development - -- **Java Components:** Use Gradle (`gradle installDist`) to build Java modules (e.g., ClavaWeaver). -- **TypeScript/JavaScript:** Use npm scripts (`npm install`, `npm run build`) in `Clava-JS`. -- **C++ Components:** Use CMake for building and integrating the Clang AST dumper. -- **Integration:** Copy built Java binaries into `Clava-JS/java-binaries` for full functionality. - -## Usage - -- **NPM Package:** - Install globally or as a project dependency: - `npm install -g @specs-feup/clava` -- **CLI:** - Run transformations via `npx clava classic -p ""` -- **CMake Integration:** - Use the `clava_weave` CMake command to apply LARA scripts to targets. - -## Code Patterns and Conventions - -- **Visitor Patterns:** - Used extensively in AST processing (see `ClangAstDumper.h`). -- **TypeScript API:** - Modular, with clear separation between API (`src-api/`) and code (`src-code/`). -- **Java:** - Follows standard Gradle project structure. -- **C++:** - Integrates with Clang/LLVM for AST extraction. - -## Common Development Tasks - -- Add new AST node support in `ClangAstDumper` and propagate through Java and JS layers. -- Extend the TypeScript API in `Clava-JS/src-api/`. -- Create new code transformations as LARA scripts or TypeScript modules. -- Use provided test scripts and npm/Gradle test commands. - -## Dependencies - -- **Node.js 20 or 22** and **Java 17+** required. -- **Clang/LLVM** for AST extraction. -- **NPM** for JS/TS dependencies. -- **Gradle** for Java builds. -- **CMake** for build system integration. - -## Troubleshooting - -- See `docs/common_issues.md` for frequently encountered problems. -- Use the GitHub issue tracker for unresolved issues. - -## References - -- [Clava Documentation](https://specs-feup.github.io/modules/_specs_feup_clava.html) -- [Clava Project Template](https://github.com/specs-feup/clava-project-template) -- [Online Demo](https://specs.fe.up.pt/tools/clava/) -- [Main Repository](https://github.com/specs-feup/clava) - ---- - -**For LLMs:** -- Respect the modular structure and language boundaries. -- When adding features, ensure changes propagate through C++, Java, and JS layers as needed. -- Follow existing patterns for AST traversal and transformation. -- Use the provided build and test scripts for validation. diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index d6a802310e..93c29172c4 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -7,6 +7,7 @@ name: "Copilot Setup Steps" on: workflow_dispatch: push: + branches: [master, staging] paths: - .github/workflows/copilot-setup-steps.yml pull_request: @@ -46,77 +47,40 @@ jobs: uses: actions/checkout@v6 with: path: clava + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Determine repository refs - id: repo-refs - shell: bash - env: - BRANCH_NAME: ${{ env.BRANCH_NAME }} - BASE_BRANCH: ${{ github.base_ref }} - run: | - set -euo pipefail - - # For each dependency repository, determine which branch to checkout. - # Priority order: - # 1. A branch with the same name as the current branch - # 2. If this is a PR, the target branch (base_ref) - # 3. The default branch of the repository - - determine_ref() { - local prefix=$1 - local repo=$2 - local url="https://github.com/${repo}.git" - - # Get the default branch - local default_branch - default_branch=$(git ls-remote --symref "$url" HEAD | awk '/^ref:/ {print $2}' | sed 's@refs/heads/@@') - echo "${prefix}_default=${default_branch}" >> "$GITHUB_OUTPUT" - echo "Default branch for ${repo} is '${default_branch}'" - - local ref_to_use="" - - # Priority 1: Same branch name - if [ -n "$(git ls-remote --heads "$url" "refs/heads/${BRANCH_NAME}")" ]; then - ref_to_use="${BRANCH_NAME}" - echo "Using matching branch '${BRANCH_NAME}' in ${repo}" - # Priority 2: PR target branch (if this is a PR) - elif [ -n "${BASE_BRANCH}" ] && [ -n "$(git ls-remote --heads "$url" "refs/heads/${BASE_BRANCH}")" ]; then - ref_to_use="${BASE_BRANCH}" - echo "Using PR target branch '${BASE_BRANCH}' in ${repo}" - # Priority 3: Default branch - else - ref_to_use="${default_branch}" - echo "Using default branch '${default_branch}' for ${repo}" - fi - - echo "${prefix}_ref=${ref_to_use}" >> "$GITHUB_OUTPUT" - } - - determine_ref "lara" "specs-feup/lara-framework" - determine_ref "specs" "specs-feup/specs-java-libs" + uses: specs-feup/branch-resolver@v1 + with: + source-directory: clava + dependencies: | + lara specs-feup/lara-framework + specs specs-feup/specs-java-libs - name: Echo checks run: | echo "Weaver branch: ${{ env.BRANCH_NAME }}" - echo "PR target branch (if any): ${{ github.base_ref }}" - echo "Lara framework ref: ${{ steps.repo-refs.outputs.lara_ref }}" - echo "Lara framework default: ${{ steps.repo-refs.outputs.lara_default }}" - echo "Specs-java-libs ref: ${{ steps.repo-refs.outputs.specs_ref }}" - echo "Specs-java-libs default: ${{ steps.repo-refs.outputs.specs_default }}" + echo "Lara framework branch: ${{ env.lara_branch }}" + echo "Lara framework commit: ${{ env.lara_ref }}" + echo "Lara framework default: ${{ env.lara_default }}" + echo "Specs-java-libs branch: ${{ env.specs_branch }}" + echo "Specs-java-libs commit: ${{ env.specs_ref }}" + echo "Specs-java-libs default: ${{ env.specs_default }}" - name: Checkout lara-framework uses: actions/checkout@v6 with: repository: specs-feup/lara-framework path: lara-framework - ref: ${{ steps.repo-refs.outputs.lara_ref }} + ref: ${{ env.lara_ref }} - name: Checkout specs-java-libs uses: actions/checkout@v6 with: repository: specs-feup/specs-java-libs path: specs-java-libs - ref: ${{ steps.repo-refs.outputs.specs_ref }} + ref: ${{ env.specs_ref }} - name: Build Weaver run: | diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1ad36291e4..270e13a5c0 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -7,6 +7,10 @@ name: nightly on: push: + # Feature branches are covered by pull_request; push only builds the + # long-lived branches to avoid duplicate runs when a PR is open. + branches: [master, staging] + pull_request: # Daily at midnight schedule: @@ -26,8 +30,8 @@ jobs: runs-on: ubuntu-latest outputs: - lara_ref: ${{ steps.repo-refs.outputs.lara_ref }} - specs_ref: ${{ steps.repo-refs.outputs.specs_ref }} + lara_ref: ${{ env.lara_ref }} + specs_ref: ${{ env.specs_ref }} steps: - name: Setup Java @@ -46,77 +50,40 @@ jobs: uses: actions/checkout@v6 with: path: clava + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Determine repository refs - id: repo-refs - shell: bash - env: - BRANCH_NAME: ${{ env.BRANCH_NAME }} - BASE_BRANCH: ${{ github.base_ref }} - run: | - set -euo pipefail - - # For each dependency repository, determine which branch to checkout. - # Priority order: - # 1. A branch with the same name as the current branch - # 2. If this is a PR, the target branch (base_ref) - # 3. The default branch of the repository - - determine_ref() { - local prefix=$1 - local repo=$2 - local url="https://github.com/${repo}.git" - - # Get the default branch - local default_branch - default_branch=$(git ls-remote --symref "$url" HEAD | awk '/^ref:/ {print $2}' | sed 's@refs/heads/@@') - echo "${prefix}_default=${default_branch}" >> "$GITHUB_OUTPUT" - echo "Default branch for ${repo} is '${default_branch}'" - - local ref_to_use="" - - # Priority 1: Same branch name - if [ -n "$(git ls-remote --heads "$url" "refs/heads/${BRANCH_NAME}")" ]; then - ref_to_use="${BRANCH_NAME}" - echo "Using matching branch '${BRANCH_NAME}' in ${repo}" - # Priority 2: PR target branch (if this is a PR) - elif [ -n "${BASE_BRANCH}" ] && [ -n "$(git ls-remote --heads "$url" "refs/heads/${BASE_BRANCH}")" ]; then - ref_to_use="${BASE_BRANCH}" - echo "Using PR target branch '${BASE_BRANCH}' in ${repo}" - # Priority 3: Default branch - else - ref_to_use="${default_branch}" - echo "Using default branch '${default_branch}' for ${repo}" - fi - - echo "${prefix}_ref=${ref_to_use}" >> "$GITHUB_OUTPUT" - } - - determine_ref "lara" "specs-feup/lara-framework" - determine_ref "specs" "specs-feup/specs-java-libs" + uses: specs-feup/branch-resolver@v1 + with: + source-directory: clava + dependencies: | + lara specs-feup/lara-framework + specs specs-feup/specs-java-libs - name: Echo checks run: | echo "Weaver branch: ${{ env.BRANCH_NAME }}" - echo "PR target branch (if any): ${{ github.base_ref }}" - echo "Lara framework ref: ${{ steps.repo-refs.outputs.lara_ref }}" - echo "Lara framework default: ${{ steps.repo-refs.outputs.lara_default }}" - echo "Specs-java-libs ref: ${{ steps.repo-refs.outputs.specs_ref }}" - echo "Specs-java-libs default: ${{ steps.repo-refs.outputs.specs_default }}" + echo "Lara framework branch: ${{ env.lara_branch }}" + echo "Lara framework commit: ${{ env.lara_ref }}" + echo "Lara framework default: ${{ env.lara_default }}" + echo "Specs-java-libs branch: ${{ env.specs_branch }}" + echo "Specs-java-libs commit: ${{ env.specs_ref }}" + echo "Specs-java-libs default: ${{ env.specs_default }}" - name: Checkout lara-framework uses: actions/checkout@v6 with: repository: specs-feup/lara-framework path: lara-framework - ref: ${{ steps.repo-refs.outputs.lara_ref }} + ref: ${{ env.lara_ref }} - name: Checkout specs-java-libs uses: actions/checkout@v6 with: repository: specs-feup/specs-java-libs path: specs-java-libs - ref: ${{ steps.repo-refs.outputs.specs_ref }} + ref: ${{ env.specs_ref }} - name: Build with Gradle run: | @@ -156,7 +123,7 @@ jobs: fail-fast: false matrix: #node-version: ['latest', '22.x', '20.x'] - node-version: ['22.x', '20.x'] + node-version: ['25.x', '24.x'] os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} @@ -187,6 +154,7 @@ jobs: uses: actions/checkout@v6 with: path: clava + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Checkout lara-framework uses: actions/checkout@v6 @@ -197,7 +165,7 @@ jobs: - name: Setup js workspace run: | - echo '{ "name": "SPeCS Workspace", "type": "module", "workspaces": [ "clava/Clava-JS", "lara-framework/Lara-JS" ] }' > package.json + echo '{ "name": "SPeCS Workspace", "type": "module", "workspaces": [ "clava/Clava-JS", "lara-framework/Lara-JS" ], "overrides": { "node-gyp": "^12.1.0" } }' > package.json npm install - name: Build Lara-JS @@ -223,25 +191,14 @@ jobs: # Only on ubuntu-latest - name: Publish JS - if: matrix.os == 'ubuntu-latest' && matrix.node-version == '22.x' + if: github.event_name == 'push' && github.ref == 'refs/heads/staging' && matrix.os == 'ubuntu-latest' && matrix.node-version == '25.x' run: | cd clava/Clava-JS npm whoami echo "Attempt to publish while running on ${{ matrix.os }} and Node.js ${{matrix.node-version}}" - if [[ "${{ github.event_name }}" == "push" ]]; then - if [ "${{ github.ref }}" == "refs/heads/staging" ]; then - echo "Publishing from staging, creating timestamped prerelease and updating tag 'staging'" - TIMESTAMP=$(date +"%Y%m%d%H%M") - npm version prerelease --preid="$TIMESTAMP" - npm publish --tag staging --access public - elif [ "${{ github.ref }}" == "refs/heads/master" ]; then - echo "Publishing from main, assumes version was changed before publishing" - npm publish - else - echo "Not master or staging branches, not publishing even if it is a push event" - fi - else - echo "Not a push event, skipping publish." - fi + echo "Publishing from staging, creating timestamped prerelease and updating tag 'staging'" + TIMESTAMP=$(date +"%Y%m%d%H%M") + npm version prerelease --preid="$TIMESTAMP" + npm publish --tag staging --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/ClangAstParser/build.gradle b/ClangAstParser/build.gradle index 26a50196fe..26f49755ed 100644 --- a/ClangAstParser/build.gradle +++ b/ClangAstParser/build.gradle @@ -22,7 +22,10 @@ dependencies { implementation ":jOptions" implementation ":SpecsUtils" + implementation 'com.google.code.gson:gson:2.12.1' implementation 'com.google.guava:guava:33.4.0-jre' + implementation 'org.apache.commons:commons-compress:1.27.1' + implementation 'org.tukaani:xz:1.9' testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.10.0' @@ -49,6 +52,11 @@ sourceSets { } } +processResources { + from('clang-dumper-release.tag') + from('cuda-release.tag') +} + // Test coverage configuration jacocoTestReport { reports { diff --git a/ClangAstParser/clang-dumper-release.tag b/ClangAstParser/clang-dumper-release.tag new file mode 100644 index 0000000000..73e74e98ff --- /dev/null +++ b/ClangAstParser/clang-dumper-release.tag @@ -0,0 +1 @@ +v18.1.8_2 diff --git a/ClangAstParser/cuda-release.tag b/ClangAstParser/cuda-release.tag new file mode 100644 index 0000000000..1701b30e16 --- /dev/null +++ b/ClangAstParser/cuda-release.tag @@ -0,0 +1 @@ +12.3.2 diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/CacheFiles.java b/ClangAstParser/src/pt/up/fe/specs/clang/CacheFiles.java new file mode 100644 index 0000000000..62fc87a58f --- /dev/null +++ b/ClangAstParser/src/pt/up/fe/specs/clang/CacheFiles.java @@ -0,0 +1,350 @@ +/** + * Copyright 2026 SPeCS. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang; + +import pt.up.fe.specs.util.SpecsIo; +import pt.up.fe.specs.util.providers.FileResourceProvider; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.OverlappingFileLockException; +import java.nio.file.AtomicMoveNotSupportedException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.FileSystemException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.FileTime; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.time.Instant; +import java.util.HexFormat; +import java.util.function.Supplier; + +final class CacheFiles { + + // FileChannel rejects overlapping locks in one JVM; this monitor serializes the small critical section. + private static final Object MAINTENANCE_MONITOR = new Object(); + private static final String MAINTENANCE_LOCK_FILENAME = ".maintenance.lock"; + + private CacheFiles() { + } + + static T withMaintenanceLock(Path cacheRoot, Supplier action) { + var lockPath = cacheRoot.resolve(MAINTENANCE_LOCK_FILENAME); + synchronized (MAINTENANCE_MONITOR) { + try { + Files.createDirectories(cacheRoot); + try (var channel = FileChannel.open(lockPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + var ignored = channel.lock()) { + return action.get(); + } + } catch (IOException e) { + throw new UncheckedIOException("Could not access cache maintenance lock '" + lockPath + "'", e); + } + } + } + + static void withMaintenanceLock(Path cacheRoot, Runnable action) { + withMaintenanceLock(cacheRoot, () -> { + action.run(); + return null; + }); + } + + static StagingDirectory createStagingDirectory(Path cacheRoot, Path parent, String prefix) { + return withMaintenanceLock(cacheRoot, () -> createStagingDirectoryLocked(parent, prefix)); + } + + private static StagingDirectory createStagingDirectoryLocked(Path parent, String prefix) { + Path lockPath; + try { + Files.createDirectories(parent); + lockPath = Files.createTempFile(parent, prefix, ".lock"); + } catch (IOException e) { + throw new UncheckedIOException("Could not create cache staging directory below '" + parent + "'", e); + } + + FileChannel channel = null; + Path stagingPath = null; + try { + channel = FileChannel.open(lockPath, StandardOpenOption.WRITE); + channel.lock(); + stagingPath = lockPath.resolveSibling(removeLockSuffix(lockPath.getFileName().toString())); + Files.createDirectory(stagingPath); + return new StagingDirectory(stagingPath, lockPath, channel); + } catch (IOException e) { + cleanupStagingCreation(stagingPath, lockPath, channel); + throw new UncheckedIOException("Could not create cache staging directory below '" + parent + "'", e); + } catch (RuntimeException e) { + cleanupStagingCreation(stagingPath, lockPath, channel); + throw e; + } + } + + static Path createTemporaryDirectory(Path parent, String prefix) { + try { + Files.createDirectories(parent); + return Files.createTempDirectory(parent, prefix); + } catch (IOException e) { + throw new UncheckedIOException("Could not create cache temporary directory below '" + parent + "'", e); + } + } + + private static String removeLockSuffix(String filename) { + return filename.substring(0, filename.length() - ".lock".length()); + } + + private static void cleanupStagingCreation(Path stagingPath, Path lockPath, FileChannel channel) { + if (channel != null) { + try { + channel.close(); + } catch (IOException ignored) { + // Best-effort cleanup after staging creation failed. + } + } + + if (stagingPath != null) { + deleteQuietly(stagingPath); + } + + try { + Files.deleteIfExists(lockPath); + } catch (IOException ignored) { + // Best-effort cleanup after staging creation failed. + } + } + + record StagingDirectory(Path path, Path lockPath, FileChannel channel) implements AutoCloseable { + + @Override + public void close() { + try { + channel.close(); + } catch (IOException e) { + throw new UncheckedIOException("Could not close cache staging lock '" + lockPath + "'", e); + } + + try { + Files.deleteIfExists(lockPath); + } catch (IOException e) { + throw new UncheckedIOException("Could not close cache staging lock '" + lockPath + "'", e); + } + } + } + + static File installFile(Path cacheRoot, File destination, FileResourceProvider resource, String expectedSha256, + String description) { + return installFile(cacheRoot, destination, resource, expectedSha256, -1, description); + } + + static File installFile(Path cacheRoot, File destination, FileResourceProvider resource, String expectedSha256, + long expectedSize, String description) { + if (destination.isFile()) { + return destination; + } + + var stagingDirectory = createStagingDirectory(cacheRoot, destination.getParentFile().toPath(), + "." + destination.getName() + ".tmp-"); + try { + File stagedFile = resource.write(stagingDirectory.path().toFile()); + if (stagedFile == null || !stagedFile.isFile()) { + throw new RuntimeException("Could not download " + description); + } + + if (expectedSize >= 0 && stagedFile.length() != expectedSize) { + throw new RuntimeException("Downloaded " + description + " does not match expected size '" + + expectedSize + "' (actual: " + stagedFile.length() + ")"); + } + + if (expectedSha256 != null && !hasExpectedSha256(stagedFile, expectedSha256)) { + throw new RuntimeException("Downloaded " + description + " does not match expected SHA-256 '" + + expectedSha256 + "'"); + } + + return publish(stagedFile.toPath(), destination.toPath()).toFile(); + } finally { + try { + deleteQuietly(stagingDirectory.path()); + } finally { + stagingDirectory.close(); + } + } + } + + static Path publish(Path staging, Path destination) { + try { + Files.createDirectories(destination.getParent()); + if (Files.exists(destination)) { + return destination; + } + + try { + Files.move(staging, destination, StandardCopyOption.ATOMIC_MOVE); + } catch (FileAlreadyExistsException e) { + // Another process completed the same object first. + } catch (AtomicMoveNotSupportedException e) { + try { + Files.move(staging, destination); + } catch (FileAlreadyExistsException ignored) { + // Another process completed the same object first. + } catch (FileSystemException collision) { + if (!Files.exists(destination)) { + throw collision; + } + + // Some file systems report a non-empty directory collision as a generic file-system exception. + } + } catch (FileSystemException e) { + if (!Files.exists(destination)) { + throw e; + } + + // Some file systems report a non-empty directory collision as a generic file-system exception. + } + + return destination; + } catch (IOException e) { + throw new UncheckedIOException("Could not publish cache object '" + destination + "'", e); + } + } + + static boolean hasExpectedSha256(File file, String expectedSha256) { + return expectedSha256.equalsIgnoreCase(calculateSha256(file)); + } + + static void touch(Path path) { + try { + Files.setLastModifiedTime(path, FileTime.from(Instant.now())); + } catch (IOException e) { + throw new UncheckedIOException("Could not update cache use time for '" + path + "'", e); + } + } + + static void deleteStaleDirectories(Path cacheRoot, Path parent, Instant cutoff, Path excluded) { + if (!Files.isDirectory(parent)) { + return; + } + + try (DirectoryStream children = Files.newDirectoryStream(parent)) { + for (Path child : children) { + if (!Files.isDirectory(child) || child.getFileName().toString().startsWith(".")) { + continue; + } + + if (excluded != null && child.toAbsolutePath().normalize().equals(excluded.toAbsolutePath().normalize())) { + continue; + } + + withMaintenanceLock(cacheRoot, () -> deleteIfStale(child, cutoff)); + } + } catch (IOException e) { + throw new UncheckedIOException("Could not clean stale cache directories below '" + parent + "'", e); + } + } + + private static void deleteIfStale(Path path, Instant cutoff) { + try { + if (Files.isDirectory(path) + && Files.getLastModifiedTime(path).toInstant().isBefore(cutoff)) { + delete(path); + } + } catch (IOException e) { + throw new UncheckedIOException("Could not inspect cache path '" + path + "'", e); + } + } + + static void deleteUnlockedStagingLocks(Path cacheRoot, Path parent) { + if (!Files.isDirectory(parent)) { + return; + } + + try (DirectoryStream locks = Files.newDirectoryStream(parent, ".*.tmp-*.lock")) { + for (Path lock : locks) { + withMaintenanceLock(cacheRoot, () -> deleteIfUnlockedStagingLock(lock)); + } + } catch (IOException e) { + throw new UncheckedIOException("Could not clean cache staging directories below '" + parent + "'", + e); + } + } + + private static void deleteIfUnlockedStagingLock(Path lockPath) { + try { + try (var channel = FileChannel.open(lockPath, StandardOpenOption.WRITE)) { + FileLock lock; + try { + lock = channel.tryLock(); + } catch (OverlappingFileLockException e) { + return; + } + + if (lock == null) { + return; + } + + try (lock) { + delete(lockPath.resolveSibling(removeLockSuffix(lockPath.getFileName().toString()))); + } + } + Files.deleteIfExists(lockPath); + } catch (NoSuchFileException e) { + // Another cleanup or publisher already removed the candidate. + } catch (IOException e) { + throw new UncheckedIOException("Could not inspect cache staging lock '" + lockPath + "'", e); + } + } + + static void delete(Path path) { + if (!Files.exists(path)) { + return; + } + + boolean deleted = path.toFile().isDirectory() + ? SpecsIo.deleteFolder(path.toFile()) + : SpecsIo.delete(path.toFile()); + if (!deleted && Files.exists(path)) { + throw new RuntimeException("Could not delete cache path '" + path + "'"); + } + } + + private static void deleteQuietly(Path path) { + try { + delete(path); + } catch (RuntimeException ignored) { + // A failed best-effort cleanup must not hide the download or extraction result. + } + } + + private static String calculateSha256(File file) { + try { + var digest = MessageDigest.getInstance("SHA-256"); + try (var inputStream = new DigestInputStream(Files.newInputStream(file.toPath()), digest)) { + inputStream.transferTo(OutputStream.nullOutputStream()); + } + + return HexFormat.of().formatHex(digest.digest()); + } catch (IOException | NoSuchAlgorithmException e) { + throw new RuntimeException("Could not calculate SHA-256 for file '" + file + "'", e); + } + } +} diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstFileResource.java b/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstFileResource.java deleted file mode 100644 index 6e2ac72f6c..0000000000 --- a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstFileResource.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright 2018 SPeCS. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package pt.up.fe.specs.clang; - -import pt.up.fe.specs.util.providers.FileResourceProvider; - -import java.util.function.Supplier; - -public enum ClangAstFileResource implements Supplier { - - LIBC_CXX_LINUX_COMPLETE(ClangAstWebResource.LIBC_CXX_LINUX_COMPLETE), - LIBC_CXX_MACOS_COMPLETE(ClangAstWebResource.LIBC_CXX_MACOS_COMPLETE), - LIBC_CXX_WIN32_COMPLETE(ClangAstWebResource.LIBC_CXX_WIN32_COMPLETE), - OPENMP_INCLUDES(ClangAstWebResource.OPENMP_INCLUDES), - CUDA_LIB(ClangAstWebResource.CUDA_LIB), - WIN_EXE(ClangAstWebResource.WIN_EXE), - WIN_DLL1(ClangAstWebResource.WIN_DLL1), - WIN_DLL2(ClangAstWebResource.WIN_DLL2), - WIN_DLL3(ClangAstWebResource.WIN_DLL3), - WIN_DLL4(ClangAstWebResource.WIN_DLL4), - WIN_DLL5(ClangAstWebResource.WIN_DLL5), - WIN_DLL6(ClangAstWebResource.WIN_DLL6), - WIN_DLL7(ClangAstWebResource.WIN_DLL7), - WIN_DLL8(ClangAstWebResource.WIN_DLL8), - WIN_DLL9(ClangAstWebResource.WIN_DLL9), - WIN_CLANG_DLL(ClangAstWebResource.WIN_CLANG_DLL), - WIN_LLVM_DLL(ClangAstWebResource.WIN_LLVM_DLL), - LINUX_EXE(ClangAstWebResource.LINUX_EXE), - LINUX_PLUGIN(ClangAstWebResource.LINUX_PLUGIN), - LINUX_LLVM_DLL(ClangAstWebResource.LINUX_LLVM_DLL), - MAC_OS_EXE(ClangAstWebResource.MAC_OS_EXE), - MAC_OS_LLVM_DLL(ClangAstWebResource.MAC_OS_LLVM_DLL), - MAC_OS_DLL1(ClangAstWebResource.MAC_OS_DLL1); - - private final FileResourceProvider provider; - - ClangAstFileResource(FileResourceProvider provider) { - this.provider = provider; - } - - @Override - public FileResourceProvider get() { - return provider; - } -} diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstKeys.java b/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstKeys.java index fd9907689b..ec17d8a8d6 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstKeys.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstKeys.java @@ -27,8 +27,6 @@ public interface ClangAstKeys { - DataKey CLANGAST_VERSION = KeyFactory.string("clangast_version", ""); - /** * What libc/libcxx mode should be used. */ @@ -55,7 +53,6 @@ public static String getFlagIgnoreIncludes() { static DataStore toDataStore(List flags) { DataStore config = DataStore.newInstance(ClavaOptions.STORE_DEFINITION, false); final String stdPrefix = "-std="; - final String clangAstDumperPrefix = "-clang-dumper="; final String cilkFlag = "-fcilkplus"; // Search options @@ -78,13 +75,6 @@ static DataStore toDataStore(List flags) { continue; } - // If ClangAstDumper version, parse option - if (flag.startsWith(clangAstDumperPrefix)) { - String version = flag.substring(clangAstDumperPrefix.length()); - config.set(ClangAstKeys.CLANGAST_VERSION, version); - continue; - } - // If Cilk flag, add option if (flag.equals(cilkFlag)) { config.set(ClangAstKeys.USES_CILK); diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstResource.java b/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstResource.java index a80188a102..c0c53d5ca1 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstResource.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstResource.java @@ -20,12 +20,9 @@ * */ public enum ClangAstResource implements ResourceProvider { - // BUILTIN_INCLUDES_3_8(ClangAstWebResource.BUILTIN_INCLUDES_3_8), - TEST_INCLUDES_C("test_includes.c"), TEST_INCLUDES_CPP("test_includes.cpp"); - // private final WebResourceProvider webResource; private final String resource; private static final String basePackage = "clangast/"; @@ -35,24 +32,10 @@ public enum ClangAstResource implements ResourceProvider { */ private ClangAstResource(String resource) { this.resource = basePackage + resource; - // this.webResource = null; } - // private ClangAstResource(WebResourceProvider webResource) { - // this.resource = null; - // this.webResource = webResource; - // } - - /* (non-Javadoc) - * @see org.suikasoft.SharedLibrary.Interfaces.ResourceProvider#getResource() - */ @Override public String getResource() { return resource; - // if (resource != null) { - // return resource; - // } - - // return webResource.getResourceUrl(); } } diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstWebResource.java b/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstWebResource.java index 3a779583da..37c62f01d7 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstWebResource.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/ClangAstWebResource.java @@ -13,40 +13,161 @@ package pt.up.fe.specs.clang; +import com.google.gson.Gson; +import pt.up.fe.specs.util.SpecsIo; import pt.up.fe.specs.util.providers.WebResourceProvider; -public interface ClangAstWebResource { +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; +import java.util.Optional; - String ROOT_16_0_5 = "https://github.com/specs-feup/clava/releases/download/clang_ast_dumper_16.0.5/"; - String ROOT_12_0_7 = "https://github.com/specs-feup/clava/releases/download/clang_ast_dumper_v12.0.7.1/"; +public final class ClangAstWebResource { - WebResourceProvider LIBC_CXX_LINUX_COMPLETE = WebResourceProvider.newInstance(ROOT_16_0_5, "libc_cxx_linux_complete.zip", "v16.0.5"); - WebResourceProvider LIBC_CXX_MACOS_COMPLETE = WebResourceProvider.newInstance(ROOT_16_0_5, "libc_cxx_macos_complete.zip", "v16.0.6"); - WebResourceProvider LIBC_CXX_WIN32_COMPLETE = WebResourceProvider.newInstance(ROOT_16_0_5, "libc_cxx_win32_complete.zip", "v16.0.5"); + private static final String RELEASE_ROOT = "https://github.com/specs-feup/clang-dumper/releases/download/"; + private static final String RELEASE_TAG_RESOURCE = "clang-dumper-release.tag"; + private static final String CUDA_RELEASE_TAG_RESOURCE = "cuda-release.tag"; + public static final String MANIFEST_FILENAME = "clang-dumper-release-manifest.json"; - WebResourceProvider OPENMP_INCLUDES = WebResourceProvider.newInstance(ROOT_16_0_5, "openmp_includes.zip"); + private static final Gson GSON = new Gson(); + private static final DumperSource DUMPER_SOURCE = readDumperSource(); - WebResourceProvider CUDA_LIB = WebResourceProvider.newInstance(ROOT_12_0_7, "cudalib.zip", "v11.3.0"); + private ClangAstWebResource() { + } - WebResourceProvider WIN_EXE = WebResourceProvider.newInstance(ROOT_16_0_5, "clang_ast_windows.exe", "v16.0.5_1"); - WebResourceProvider WIN_DLL1 = WebResourceProvider.newInstance(ROOT_12_0_7, "libwinpthread-1.dll"); - WebResourceProvider WIN_DLL2 = WebResourceProvider.newInstance(ROOT_12_0_7, "zlib1.dll"); - WebResourceProvider WIN_DLL3 = WebResourceProvider.newInstance(ROOT_12_0_7, "libzstd.dll"); - WebResourceProvider WIN_DLL4 = WebResourceProvider.newInstance(ROOT_12_0_7, "libstdc++-6.dll"); - WebResourceProvider WIN_DLL5 = WebResourceProvider.newInstance(ROOT_12_0_7, "libgcc_s_seh-1.dll"); - WebResourceProvider WIN_DLL6 = WebResourceProvider.newInstance(ROOT_12_0_7, "libffi-8.dll"); - WebResourceProvider WIN_DLL7 = WebResourceProvider.newInstance(ROOT_12_0_7, "libxml2-2.dll"); - WebResourceProvider WIN_DLL8 = WebResourceProvider.newInstance(ROOT_12_0_7, "liblzma-5.dll"); - WebResourceProvider WIN_DLL9 = WebResourceProvider.newInstance(ROOT_12_0_7, "libiconv-2.dll"); - WebResourceProvider WIN_LLVM_DLL = WebResourceProvider.newInstance(ROOT_16_0_5, "libLLVM-16.dll"); - WebResourceProvider WIN_CLANG_DLL = WebResourceProvider.newInstance(ROOT_16_0_5, "libclang-cpp.dll"); + public static DumperSource getDumperSource() { + return DUMPER_SOURCE; + } - WebResourceProvider LINUX_EXE = WebResourceProvider.newInstance(ROOT_16_0_5, "clang_ast_linux", "v16.0.5"); - WebResourceProvider LINUX_PLUGIN = WebResourceProvider.newInstance(ROOT_16_0_5, "clang-plugin.so", "v16.0.5"); - WebResourceProvider LINUX_LLVM_DLL = WebResourceProvider.newInstance(ROOT_16_0_5, "libLLVM-16.so.1", "v16.0.5"); + private static DumperSource readDumperSource() { + return parseDumperSource(readReleaseTag(RELEASE_TAG_RESOURCE)); + } - WebResourceProvider MAC_OS_EXE = WebResourceProvider.newInstance(ROOT_16_0_5, "clang_ast_macos", "v16.0.5"); - WebResourceProvider MAC_OS_LLVM_DLL = WebResourceProvider.newInstance(ROOT_16_0_5, "libLLVM.dylib", "v16.0.5"); - WebResourceProvider MAC_OS_DLL1 = WebResourceProvider.newInstance(ROOT_16_0_5, "libzstd.1.dylib", "v16.0.5"); + private static String readReleaseTag(String resourceName) { + var inputStream = ClangAstWebResource.class.getClassLoader().getResourceAsStream(resourceName); + if (inputStream == null) { + throw new RuntimeException("Could not find resource '" + resourceName + "'"); + } + + String value; + try (inputStream) { + value = SpecsIo.read(inputStream).trim(); + } catch (IOException e) { + throw new UncheckedIOException("Could not read resource '" + resourceName + "'", e); + } + + if (value.isBlank()) { + throw new RuntimeException("Resource '" + resourceName + "' is empty"); + } + + return value; + } + + static DumperSource parseDumperSource(String value) { + var path = Path.of(value); + if (path.isAbsolute()) { + return new LocalBuild(path.toFile()); + } + + if (value.contains("/") || value.contains("\\") || value.equals(".") || value.equals("..")) { + throw new RuntimeException("Relative paths are not supported in resource '" + RELEASE_TAG_RESOURCE + + "': '" + value + "'"); + } + + return new Release(value); + } + + public static String getReleaseTag() { + var source = getDumperSource(); + if (source instanceof Release release) { + return release.tag(); + } + + throw new IllegalStateException("The clang-dumper resource points to a local build"); + } + + public static String getCudaReleaseTag() { + var releaseTag = readReleaseTag(CUDA_RELEASE_TAG_RESOURCE); + if (releaseTag.equals(".") || releaseTag.equals("..") + || releaseTag.contains("/") || releaseTag.contains("\\")) { + throw new RuntimeException("Release resource '" + CUDA_RELEASE_TAG_RESOURCE + + "' must contain a single path component: '" + releaseTag + "'"); + } + + return releaseTag; + } + + public static ClangDumperManifest getManifest(File resourceFolder) { + var releaseTag = getReleaseTag(); + var manifestResource = WebResourceProvider.newInstance(getReleaseBaseUrl(releaseTag), MANIFEST_FILENAME, + releaseTag); + var cacheRoot = resourceFolder.toPath().getParent().getParent(); + var manifestFile = CacheFiles.installFile(cacheRoot, new File(resourceFolder, MANIFEST_FILENAME), + manifestResource, null, "clang-dumper release manifest"); + var manifest = GSON.fromJson(SpecsIo.read(manifestFile), ClangDumperManifest.class); + + if (manifest == null) { + throw new RuntimeException("Could not parse clang-dumper manifest from '" + manifestFile + "'"); + } + + manifest.validate(); + return manifest; + } + + public static WebResourceProvider getAssetResource(ClangDumperManifestAsset asset) { + var releaseTag = getReleaseTag(); + return WebResourceProvider.newInstance(getReleaseBaseUrl(releaseTag), asset.filename(), + releaseTag + "-" + asset.sha256()); + } + + private static String getReleaseBaseUrl(String releaseTag) { + return RELEASE_ROOT + releaseTag + "/"; + } + + public sealed interface DumperSource permits Release, LocalBuild { + } + + public record Release(String tag) implements DumperSource { + } + + public record LocalBuild(File folder) implements DumperSource { + } + + public record ClangDumperManifest(int schema_version, List assets) { + + public void validate() { + if (schema_version != 1) { + throw new RuntimeException("Unsupported clang-dumper manifest schema version: " + schema_version); + } + + if (assets == null || assets.isEmpty()) { + throw new RuntimeException("Clang-dumper manifest does not contain assets"); + } + } + + public ClangDumperManifestAsset getAsset(String platform, String arch, String kind) { + Objects.requireNonNull(platform); + Objects.requireNonNull(arch); + Objects.requireNonNull(kind); + + Optional asset = assets.stream() + .filter(candidate -> candidate.matches(platform, arch, kind)) + .findFirst(); + + return asset.orElseThrow(() -> new RuntimeException("Could not find clang-dumper asset for platform '" + + platform + "', architecture '" + arch + "' and kind '" + kind + "'")); + } + } + + public record ClangDumperManifestAsset(String filename, String kind, String platform, String arch, int llvm_major, + String sha256) { + + public boolean matches(String platform, String arch, String kind) { + return this.platform.equals(platform) && this.arch.equals(arch) && this.kind.equals(kind); + } + } } diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/ClangFiles.java b/ClangAstParser/src/pt/up/fe/specs/clang/ClangFiles.java index 731cac065f..d250a9ab85 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/ClangFiles.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/ClangFiles.java @@ -15,7 +15,15 @@ import java.io.File; import java.util.List; +import java.util.Objects; -public record ClangFiles(File clangExecutable, List builtinIncludes) { +public record ClangFiles(File clangExecutable, List builtinIncludes, File systemResourceDir, + LibcMode libcMode) { + public ClangFiles { + Objects.requireNonNull(libcMode, "libcMode"); + if (libcMode == LibcMode.AUTO) { + throw new IllegalArgumentException("Clang files must use a concrete libc mode"); + } + } } diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/ClangResources.java b/ClangAstParser/src/pt/up/fe/specs/clang/ClangResources.java index 3aa4b56598..041f66e569 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/ClangResources.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/ClangResources.java @@ -13,6 +13,9 @@ package pt.up.fe.specs.clang; +import pt.up.fe.specs.clang.ClangAstWebResource.ClangDumperManifest; +import pt.up.fe.specs.clang.ClangAstWebResource.ClangDumperManifestAsset; +import pt.up.fe.specs.clang.ClangAstWebResource.LocalBuild; import pt.up.fe.specs.clang.codeparser.CodeParser; import pt.up.fe.specs.clang.dumper.ClangAstDumper; import pt.up.fe.specs.clang.parsers.TopLevelNodesParser; @@ -20,382 +23,560 @@ import pt.up.fe.specs.util.SpecsIo; import pt.up.fe.specs.util.SpecsLogs; import pt.up.fe.specs.util.SpecsSystem; -import pt.up.fe.specs.util.lazy.Lazy; -import pt.up.fe.specs.util.providers.FileResourceManager; import pt.up.fe.specs.util.providers.FileResourceProvider; -import pt.up.fe.specs.util.providers.FileResourceProvider.ResourceWriteData; import pt.up.fe.specs.util.system.ProcessOutputAsString; import java.io.File; -import java.util.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; public class ClangResources { - private static final FileResourceManager CLANG_AST_RESOURCES = FileResourceManager - .fromEnum(ClangAstFileResource.class); + private static final Map CLANG_FILES_CACHE = new ConcurrentHashMap<>(); + private static final String CLANG_FOLDERNAME = "clang_ast_exe"; + private static final String CLANG_CACHE_FOLDERNAME = "clang-dumper"; + private static final String RELEASES_FOLDERNAME = "releases"; + private static final String INCLUDES_FOLDERNAME = "includes"; + private static final Duration STALE_CACHE_MAX_AGE = Duration.ofDays(60); - private static final Map CLANG_FILES_CACHE = new ConcurrentHashMap<>(); - - private final static String CLANG_FOLDERNAME = "clang_ast_exe"; - - private final Lazy cudalibFolder = Lazy.newInstance(this::prepareBuiltinCudaLib); + private static final Map HAS_LIBC = new ConcurrentHashMap<>(); private final CodeParser options; - - private static final AtomicInteger HAS_LIBC = new AtomicInteger(-1); - public ClangResources(CodeParser options) { this.options = options; } - public ClangFiles getClangFiles(String version, LibcMode libcMode) { + public static boolean isBuiltinCudaSupported() { + return CudaResources.isSupportedPlatform(); + } + + public File getBuiltinCudaLib() { + return CudaResources.getBuiltinCudaLib(options.get(CodeParser.DUMPER_FOLDER).toPath()); + } + + public ClangFiles getClangFiles(LibcMode requestedLibcMode) { - // Create key - var key = libcMode.name() + "_" + version + "_" + getClangResourceFolder().getAbsolutePath(); + var source = ClangAstWebResource.getDumperSource(); + var useBuiltinCuda = options.get(CodeParser.CUDA_PATH).equalsIgnoreCase(CodeParser.getBuiltinOption()); + var forceSystemLibc = source instanceof LocalBuild || ClangAstDumper.usePlugin(); - // Check if cached - var files = CLANG_FILES_CACHE.get(key); - if (files != null) { - SpecsLogs.debug(() -> "Using cached version of Clang files: " + files); - return files; + if (source instanceof LocalBuild localBuild) { + var clangExecutable = getLocalExecutable(localBuild.folder()); + var libcMode = resolveLibcMode(clangExecutable, requestedLibcMode, forceSystemLibc); + var systemResourceDir = libcMode == LibcMode.SYSTEM && useBuiltinCuda + ? findSystemClangResourceDir(null) + : null; + return new ClangFiles(clangExecutable, List.of(), systemResourceDir, libcMode); } - File clangExecutable = prepareResources(version); - List builtinIncludes = prepareIncludes(clangExecutable, libcMode); + var resourceFolder = getClangResourceFolder(); + var manifest = ClangAstWebResource.getManifest(resourceFolder); + File clangExecutable = prepareResources(manifest, resourceFolder); + var libcMode = resolveLibcMode(clangExecutable, requestedLibcMode, forceSystemLibc); + var key = libcMode.name() + "_" + useBuiltinCuda + "_" + source + "_" + resourceFolder.getAbsolutePath(); + var cached = CLANG_FILES_CACHE.get(key); + if (isUsable(cached)) { + SpecsLogs.debug(() -> "Using cached version of Clang files: " + cached.files()); + return cached.files(); + } - var newFiles = new ClangFiles(clangExecutable, builtinIncludes); - SpecsLogs.debug(() -> "Using downloaded version of Clang files: " + newFiles); + if (cached != null) { + CLANG_FILES_CACHE.remove(key, cached); + } - // Store in cache - CLANG_FILES_CACHE.put(key, newFiles); + var includes = prepareIncludes(manifest, libcMode); + var systemResourceDir = libcMode == LibcMode.SYSTEM && useBuiltinCuda + ? prepareSystemClangResourceDir(manifest) + : null; + + if (useBuiltinCuda) { + getBuiltinCudaLib(); + } - return newFiles; + touchUse(resourceFolder, includes.extractedFolder()); + updateLastUsedAndCleanupStaleVersions(resourceFolder, includes.extractedFolder()); + + var newFiles = new CachedClangFiles(new ClangFiles(clangExecutable, includes.folders(), systemResourceDir, + libcMode), + includes.extractedFolder()); + var existingFiles = CLANG_FILES_CACHE.putIfAbsent(key, newFiles); + var selectedFiles = existingFiles == null ? newFiles : existingFiles; + touchUse(resourceFolder, selectedFiles.includesFolder()); + SpecsLogs.debug(() -> "Using downloaded version of Clang files: " + selectedFiles.files()); + return selectedFiles.files(); } - /** - * @return path to the executable that was copied - */ - private File prepareResources(String version) { + static LibcMode resolveLibcMode(File clangExecutable, LibcMode requestedLibcMode, boolean forceSystem) { + Objects.requireNonNull(clangExecutable, "clangExecutable"); + Objects.requireNonNull(requestedLibcMode, "requestedLibcMode"); - File resourceFolder = getClangResourceFolder(); + if (forceSystem) { + return LibcMode.SYSTEM; + } - SupportedPlatform platform = SupportedPlatform.getCurrentPlatform(); - FileResourceProvider executableResource = getVersionedResource(getExecutableResource(platform), version); + return switch (requestedLibcMode) { + case AUTO -> useBuiltinLibc(clangExecutable, requestedLibcMode) + ? LibcMode.BUILTIN_AND_LIBC + : LibcMode.SYSTEM; + case BUILTIN_AND_LIBC, SYSTEM -> requestedLibcMode; + }; + } - // Copy executable - ResourceWriteData executable = executableResource.writeVersioned(resourceFolder, ClangResources.class); + private boolean isUsable(CachedClangFiles cached) { + if (cached == null) { + return false; + } - // If Windows, copy additional dependencies - if (platform == SupportedPlatform.WINDOWS) { - for (FileResourceProvider resource : getWindowsResources()) { - resource.writeVersioned(resourceFolder, ClangResources.class); + return CacheFiles.withMaintenanceLock(getClangCacheRoot().toPath(), () -> { + if (!cached.files().clangExecutable().isFile()) { + return false; } - } else if (platform == SupportedPlatform.MAC_OS) { - for (FileResourceProvider resource : getMacOSResources()) { - resource.writeVersioned(resourceFolder, ClangResources.class); + + if (cached.files().systemResourceDir() != null + && !cached.files().systemResourceDir().isDirectory()) { + return false; } - } else if (platform == SupportedPlatform.LINUX) { - for (FileResourceProvider resource : getLinuxResources()) { - resource.writeVersioned(resourceFolder, ClangResources.class); + + var includesFolder = cached.includesFolder(); + if (includesFolder == null) { + return true; } - } - // If on Windows, preemptively unblock file, due to possible Mark-of-the-Web restrictions - if (platform.isWindows()) { - var command = List.of(SpecsSystem.getWindowsPowershell(), "-NoLogo", "-NoProfile", "-NonInteractive", - "-ExecutionPolicy", "Bypass", - "-Command", - "Unblock-File", - "-Path", - "\"" + executable.getFile().getAbsolutePath() + "\"", - "-ErrorAction", - "Stop" - ); - - var output = SpecsSystem.runProcess(command, true, true); - if (output.getReturnValue() == 0) { - SpecsLogs.info("Successfully unblocked dumper executable"); - } else { - SpecsLogs.info("Could not unblock dumper executable"); + if (!includesFolder.exists()) { + return false; + } + + CacheFiles.touch(includesFolder.toPath()); + if (!isIncludesCacheValid(includesFolder)) { + throw invalidIncludesCache(includesFolder, includesFolder.getName()); } + + return true; + }); + } + + private void touchUse(File resourceFolder, File includesFolder) { + CacheFiles.withMaintenanceLock(getClangCacheRoot().toPath(), () -> { + CacheFiles.touch(resourceFolder.toPath()); + if (includesFolder != null) { + CacheFiles.touch(includesFolder.toPath()); + } + }); + } + + static File getLocalExecutable(File buildFolder) { + if (!buildFolder.isDirectory()) { + throw new RuntimeException("Local clang-dumper build directory does not exist: '" + buildFolder + "'"); + } + + String filename; + if (ClangAstDumper.usePlugin()) { + filename = System.mapLibraryName("plugin"); + } else { + filename = SupportedPlatform.getCurrentPlatform().isWindows() ? "tool.exe" : "tool"; } - // If file is new and we are in a flavor of Linux or MacOS, make file executable - if (executable.isNewFile() && (platform.isLinux() || platform.isMacOs())) { - SpecsSystem.runProcess(Arrays.asList("chmod", "+x", executable.getFile().getAbsolutePath()), false, true); + var executable = new File(buildFolder, filename); + if (!executable.isFile()) { + throw new RuntimeException("Could not find local clang-dumper " + + (ClangAstDumper.usePlugin() ? "plugin" : "tool") + " '" + executable + "'"); } - return executable.getFile(); + SpecsLogs.info("Using local clang-dumper build: " + executable); + return executable; } - private FileResourceProvider getVersionedResource(FileResourceProvider resource, String version) { + private File prepareResources(ClangDumperManifest manifest, File resourceFolder) { + SupportedPlatform platform = SupportedPlatform.getCurrentPlatform(); + + var executableKind = ClangAstDumper.usePlugin() ? "plugin" : "tool"; + var asset = getCurrentAsset(manifest, executableKind); + File executable = CacheFiles.installFile(getClangCacheRoot().toPath(), + new File(resourceFolder, asset.filename()), + ClangAstWebResource.getAssetResource(asset), asset.sha256(), + "clang-dumper asset '" + asset.filename() + "'"); - // If version not defined, use the latest version of the resource - if (version.isEmpty()) { - version = resource.version(); + if (platform.isWindows()) { + unblockWindowsFile(executable); } - // ClangAst executable versions are separated by an underscore - resource = resource.createResourceVersion("_" + version); - return resource; + if (platform.isLinux() || platform.isMacOs()) { + SpecsSystem.runProcess(Arrays.asList("chmod", "+x", executable.getAbsolutePath()), false, true); + } + + return executable; + } + + private void unblockWindowsFile(File executable) { + var command = List.of(SpecsSystem.getWindowsPowershell(), "-NoLogo", "-NoProfile", "-NonInteractive", + "-ExecutionPolicy", "Bypass", + "-Command", + "Unblock-File", + "-Path", + "\"" + executable.getAbsolutePath() + "\"", + "-ErrorAction", + "Stop" + ); + + var output = SpecsSystem.runProcess(command, true, true); + if (output.getReturnValue() == 0) { + SpecsLogs.info("Successfully unblocked dumper executable"); + } else { + SpecsLogs.info("Could not unblock dumper executable"); + } } public File getClangResourceFolder() { - return options.get(CodeParser.DUMPER_FOLDER); + var cacheFolder = getClangCacheRoot(); + return CacheFiles.withMaintenanceLock(cacheFolder.toPath(), () -> { + var releaseFolder = SpecsIo.mkdir(getReleasesFolder(), ClangAstWebResource.getReleaseTag()); + CacheFiles.touch(releaseFolder.toPath()); + return releaseFolder; + }); } public static File getDefaultTempFolder() { return SpecsIo.getTempFolder(CLANG_FOLDERNAME); } - private FileResourceProvider getExecutableResource(SupportedPlatform platform) { - switch (platform) { - case WINDOWS: - return CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_EXE); - case LINUX: - if (ClangAstDumper.usePlugin()) { - return CLANG_AST_RESOURCES.get(ClangAstFileResource.LINUX_PLUGIN); - } else { - return CLANG_AST_RESOURCES.get(ClangAstFileResource.LINUX_EXE); - } - - case MAC_OS: - return CLANG_AST_RESOURCES.get(ClangAstFileResource.MAC_OS_EXE); - default: - throw new RuntimeException("Case not defined: '" + platform + "'"); - } + private File getReleasesFolder() { + return SpecsIo.mkdir(getClangCacheRoot(), RELEASES_FOLDERNAME); } - private List getWindowsResources() { - List windowsResources = new ArrayList<>(); - - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL1)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL2)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL3)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL4)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL5)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL6)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL7)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL8)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_DLL9)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_CLANG_DLL)); - windowsResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.WIN_LLVM_DLL)); - - return windowsResources; + private File getIncludesRoot() { + return new File(getClangCacheRoot(), INCLUDES_FOLDERNAME); } - private List getMacOSResources() { - List macosResources = new ArrayList<>(); - - macosResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.MAC_OS_LLVM_DLL)); - macosResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.MAC_OS_DLL1)); - - return macosResources; + private File getClangCacheRoot() { + return new File(options.get(CodeParser.DUMPER_FOLDER), CLANG_CACHE_FOLDERNAME); } - private List getLinuxResources() { - List linuxResources = new ArrayList<>(); + static File getSharedIncludesFolder(File cacheFolder, String sha256) { + return new File(new File(cacheFolder, INCLUDES_FOLDERNAME), sha256.toLowerCase(Locale.ROOT)); + } - linuxResources.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.LINUX_LLVM_DLL)); + public static boolean useBuiltinLibc(File clangExecutable, LibcMode libcMode) { + return switch (libcMode) { + case AUTO -> !hasLibC(clangExecutable); + case BUILTIN_AND_LIBC -> true; + case SYSTEM -> false; + }; + } - return linuxResources; + private static boolean hasLibC(File clangExecutable) { + var executableKey = SpecsIo.getCanonicalPath(clangExecutable); + return HAS_LIBC.computeIfAbsent(executableKey, ignored -> detectLibC(clangExecutable)); } - private List prepareIncludes(File clangExecutable, LibcMode libcMode) { + private static boolean detectLibC(File clangExecutable) { + File clangTest = SpecsIo.getTempFolder("clang_ast_test_" + UUID.randomUUID()); - // Get base resource folder - File resourceFolder = getClangResourceFolder(); + try { + var testFiles = List.of( + ClangAstResource.TEST_INCLUDES_C.write(clangTest), + ClangAstResource.TEST_INCLUDES_CPP.write(clangTest)); - // Create list of include zips - List includesZips = new ArrayList<>(); + boolean needsLib = false; + for (var testFile : testFiles) { + var output = runClangAstDumper(clangExecutable, testFile); - // Get libc/libcxx resources, if required - if (useBuiltinLibc(clangExecutable, libcMode)) { + if (output.getReturnValue() != 0) { + ClavaLog.info("Problems while running dumper to test if libc/libcxx is needed"); + needsLib = true; + break; + } - // MacOS - if (SupportedPlatform.getCurrentPlatform().isMacOs()) { - var macosBuiltinResource = CLANG_AST_RESOURCES.get(ClangAstFileResource.LIBC_CXX_MACOS_COMPLETE); - includesZips.add(getVersionedResource(macosBuiltinResource, macosBuiltinResource.version())); - } - // Linux - else if (SupportedPlatform.getCurrentPlatform().isLinux()) { - var linuxBuiltinResource = CLANG_AST_RESOURCES.get(ClangAstFileResource.LIBC_CXX_LINUX_COMPLETE); - includesZips.add(getVersionedResource(linuxBuiltinResource, linuxBuiltinResource.version())); + if (testFile.getName().endsWith(".cpp") + && !output.getOutput().contains(TopLevelNodesParser.getTopLevelNodesHeader())) { + needsLib = true; + break; + } } - // Windows - else if (SupportedPlatform.getCurrentPlatform().isWindows()) { - var windowsBuiltinResource = CLANG_AST_RESOURCES.get(ClangAstFileResource.LIBC_CXX_WIN32_COMPLETE); - includesZips.add(getVersionedResource(windowsBuiltinResource, windowsBuiltinResource.version())); + + if (needsLib) { + ClavaLog.debug("Could not find system libc/libcxx"); } else { - throw new RuntimeException("Unsupported platform: " + SupportedPlatform.getCurrentPlatform()); + ClavaLog.debug("Detected system's libc and libcxx"); } - + return !needsLib; + } finally { + SpecsIo.deleteFolder(clangTest); } + } - // Always add OpenMP includes - includesZips.add(CLANG_AST_RESOURCES.get(ClangAstFileResource.OPENMP_INCLUDES)); - - // Download includes zips, later we check if any of them is new - List zipFiles = includesZips.stream() - .map(resource -> resource.writeVersioned(resourceFolder, ClangResources.class)) - .collect(Collectors.toList()); - + private static ProcessOutputAsString runClangAstDumper(File clangExecutable, File testFile) { + List arguments = List.of(clangExecutable.getAbsolutePath(), testFile.getAbsolutePath(), "--"); + return SpecsSystem.runProcess(arguments, true, false); + } - var extractedFolders = new ArrayList(); + private PreparedIncludes prepareIncludes(ClangDumperManifest manifest, LibcMode libcMode) { + if (libcMode == LibcMode.SYSTEM) { + return new PreparedIncludes(List.of(), null); + } - // If a new file has been written or if folder exists but is empty, delete corresponding includes folder, and extract zip again - for (var zipFile : zipFiles) { + var extractedFolder = prepareIncludesFolder(manifest); + var includeFolders = getIncludeFolders(extractedFolder); + SpecsLogs.debug(() -> "Includes folders: " + includeFolders); - // Obtain folder for zip - var zipFoldername = "include_" + SpecsIo.removeExtension(zipFile.getFile()); - var extractedFolder = SpecsIo.mkdir(resourceFolder, zipFoldername); + return new PreparedIncludes(includeFolders.stream().map(File::getAbsolutePath).toList(), extractedFolder); + } - // Add to extracted folders list - extractedFolders.add(extractedFolder); + private File prepareSystemClangResourceDir(ClangDumperManifest manifest) { + var executableKind = ClangAstDumper.usePlugin() ? "plugin" : "tool"; + var llvmMajor = getCurrentAsset(manifest, executableKind).llvm_major(); + return findSystemClangResourceDir(llvmMajor); + } - // Skip extraction if zip is not new and folder is not empty - if (!zipFile.isNewFile() && !SpecsIo.isEmptyFolder(extractedFolder)) { + private File findSystemClangResourceDir(Integer llvmMajor) { + var commandNames = getSystemClangCommandNames(llvmMajor); + for (var commandName : commandNames) { + final ProcessOutputAsString output; + try { + output = SpecsSystem.runProcess(List.of(commandName, "-print-resource-dir"), true, false); + } catch (RuntimeException e) { continue; } - // Clean folder - SpecsIo.deleteFolderContents(extractedFolder); + if (output.getReturnValue() != 0 || output.getStdOut() == null) { + continue; + } - // Extract zip contents to folder - SpecsIo.extractZip(zipFile.getFile(), extractedFolder); + var resourceDir = new File(output.getStdOut().trim()); + if (isSystemClangResourceDir(resourceDir, llvmMajor)) { + SpecsLogs.debug(() -> "Using system Clang resource directory '" + + resourceDir.getAbsolutePath() + "'"); + return resourceDir; + } } - // Add all folders inside extracted folders as system include - var includesFiles = new ArrayList(); - for (var extractedFolder : extractedFolders) { - var includeFolders = SpecsIo.getFolders(extractedFolder); + var expectedVersion = llvmMajor == null ? "the local clang-dumper build's version" + : "LLVM " + llvmMajor; + throw new RuntimeException("Could not find a system Clang resource directory for SYSTEM mode with built-in CUDA" + + " on host '" + SupportedPlatform.getCurrentPlatform() + "' (expected " + expectedVersion + + "). Tried: " + commandNames); + } - includesFiles.addAll(includeFolders); + private static List getSystemClangCommandNames(Integer llvmMajor) { + var suffix = SupportedPlatform.getCurrentPlatform().isWindows() ? ".exe" : ""; + if (llvmMajor == null) { + return List.of("clang++" + suffix); } - - // Sort them alphabetically, by last foldername, include order is important - Collections.sort(includesFiles, Comparator.comparing(File::getName)); - SpecsLogs.debug(() -> "Includes folders: " + includesFiles); - - return includesFiles.stream().map(File::getAbsolutePath).toList(); + return List.of("clang++-" + llvmMajor + suffix, "clang++" + suffix); } - public static boolean useBuiltinLibc(File clangExecutable, LibcMode libcMode) { + private static boolean isSystemClangResourceDir(File resourceDir, Integer llvmMajor) { + if (!resourceDir.isDirectory() || !new File(resourceDir, "include").isDirectory()) { + return false; + } - return switch (libcMode) { - case AUTO -> !hasLibC(clangExecutable); - case BUILTIN_AND_LIBC -> true; - case SYSTEM -> false; - }; + return llvmMajor == null || resourceDir.getName().equals(Integer.toString(llvmMajor)); } - private static boolean hasLibC(File clangExecutable) { - var value = HAS_LIBC.get(); + private File prepareIncludesFolder(ClangDumperManifest manifest) { + var includesAsset = getCurrentAsset(manifest, "includes"); + return resolveIncludes(getClangCacheRoot(), includesAsset, + ClangAstWebResource.getAssetResource(includesAsset)); + } - // Check if initiallized - if (value == -1) { - var hasLibC = detectLibC(clangExecutable); - value = hasLibC ? 1 : 0; - HAS_LIBC.set(value); + static File resolveIncludes(File cacheFolder, ClangDumperManifestAsset includesAsset, + FileResourceProvider archiveResource) { + var extractedFolder = getSharedIncludesFolder(cacheFolder, includesAsset.sha256()); + var existingFolder = useExistingIncludes(cacheFolder, extractedFolder, includesAsset.sha256()); + if (existingFolder != null) { + return existingFolder; } - if (value == 0) { - return false; - } + var includesRoot = extractedFolder.getParentFile().toPath(); + CacheFiles.deleteUnlockedStagingLocks(cacheFolder.toPath(), includesRoot); + var stagingFolder = CacheFiles.createStagingDirectory(cacheFolder.toPath(), includesRoot, + "." + includesAsset.sha256() + ".tmp-"); + try { + var downloadFolder = CacheFiles.createTemporaryDirectory(stagingFolder.path(), ".download-"); + try { + var archive = archiveResource.write(downloadFolder.toFile()); + if (archive == null || !archive.isFile()) { + throw new RuntimeException("Could not download clang-dumper includes archive '" + + includesAsset.filename() + "'"); + } - if (value == 1) { - return true; - } + if (!CacheFiles.hasExpectedSha256(archive, includesAsset.sha256())) { + throw new RuntimeException("Downloaded clang-dumper asset '" + includesAsset.filename() + + "' does not match expected SHA-256 '" + includesAsset.sha256() + "'"); + } - throw new RuntimeException("Unexpected value: '" + value + "'"); - } + if (!SpecsIo.extractZip(archive, stagingFolder.path().toFile())) { + throw new RuntimeException("Could not extract clang-dumper includes archive '" + + includesAsset.filename() + "'"); + } + } finally { + CacheFiles.delete(downloadFolder); + } - /** - * Detects if the system has libc/licxx installed. - * - * @param clangExecutable - * @return - */ - private static boolean detectLibC(File clangExecutable) { + getIncludeFolders(stagingFolder.path().toFile()); + existingFolder = useExistingIncludes(cacheFolder, extractedFolder, includesAsset.sha256()); + if (existingFolder != null) { + return existingFolder; + } - File clangTest = SpecsIo.mkdir(SpecsIo.getTempFolder(), "clang_ast_test"); + var publishedFolder = CacheFiles.publish(stagingFolder.path(), extractedFolder.toPath()).toFile(); + existingFolder = useExistingIncludes(cacheFolder, publishedFolder, includesAsset.sha256()); + if (existingFolder == null) { + throw new RuntimeException("Published clang-dumper includes disappeared: '" + + publishedFolder.getAbsolutePath() + "'"); + } - // Write test files - List testFiles = Arrays.asList(ClangAstResource.TEST_INCLUDES_C, ClangAstResource.TEST_INCLUDES_CPP) - .stream() - .map(resource -> resource.write(clangTest)) - .collect(Collectors.toList()); + return existingFolder; + } finally { + try { + CacheFiles.delete(stagingFolder.path()); + } finally { + stagingFolder.close(); + } + } + } - boolean needsLib = false; - for (File testFile : testFiles) { + private static File useExistingIncludes(File cacheFolder, File includesFolder, String sha256) { + if (!includesFolder.exists()) { + return null; + } - // Invoke dumper - var output = runClangAstDumper(clangExecutable, testFile); + return CacheFiles.withMaintenanceLock(cacheFolder.toPath(), () -> { + if (!includesFolder.exists()) { + return null; + } - // First check if there where no problems running the dumper - if (output.getReturnValue() != 0) { - ClavaLog.info("Problems while running dumper to test in libc/libcxx is needed"); - needsLib = true; - break; + CacheFiles.touch(includesFolder.toPath()); + if (!isIncludesCacheValid(includesFolder)) { + throw invalidIncludesCache(includesFolder, sha256); } - // Test files where built in such a way so that if a system include is present, it will generate code with a - // top level nodes, otherwise it generates an empty file - var topLevelNodesHeader = TopLevelNodesParser.getTopLevelNodesHeader(); + return includesFolder; + }); + } - var foundInclude = output.getOutput().contains(topLevelNodesHeader); + private static RuntimeException invalidIncludesCache(File includesFolder, String sha256) { + return new RuntimeException("Invalid clang-dumper includes cache directory '" + + includesFolder.getAbsolutePath() + "' for SHA-256 '" + sha256 + + "'; delete this directory manually to regenerate"); + } - if (!foundInclude) { - needsLib = true; - break; - } + static List getIncludeFolders(File extractedFolder) { + if (!extractedFolder.isDirectory()) { + throw new RuntimeException("Could not find extracted clang-dumper includes folder '" + extractedFolder + "'"); + } + var entrypointsFile = new File(extractedFolder, "entrypoints.txt"); + if (!entrypointsFile.isFile()) { + throw new RuntimeException("Could not find include archive entrypoints file '" + entrypointsFile + "'"); } - if (needsLib) { - ClavaLog.debug("Could not find system libc/libcxx"); - } else { - ClavaLog.debug("Detected system's libc and libcxx"); + Path root = extractedFolder.toPath().toAbsolutePath().normalize(); + var includeFolders = new ArrayList(); + var entrypoints = SpecsIo.read(entrypointsFile).lines() + .map(String::trim) + .filter(value -> !value.isEmpty()) + .toList(); + for (String line : entrypoints) { + Path includeFolder = root.resolve(line).normalize(); + if (!includeFolder.startsWith(root) || !Files.isDirectory(includeFolder)) { + throw new RuntimeException("Include archive entrypoint is not a usable directory: '" + line + "'"); + } + + includeFolders.add(includeFolder.toFile()); } - return !needsLib; + return includeFolders; + } + private ClangDumperManifestAsset getCurrentAsset(ClangDumperManifest manifest, String kind) { + var platform = getManifestPlatform(); + var arch = getManifestArch(platform); + return manifest.getAsset(platform, arch, kind); } - private static ProcessOutputAsString runClangAstDumper(File clangExecutable, File testFile) { - List arguments = Arrays.asList(clangExecutable.getAbsolutePath(), testFile.getAbsolutePath(), "--"); - return SpecsSystem.runProcess(arguments, true, false); + static boolean isIncludesCacheValid(File includesFolder) { + try { + getIncludeFolders(includesFolder); + return true; + } catch (RuntimeException e) { + SpecsLogs.info("Cached clang-dumper includes are invalid: " + includesFolder); + return false; + } } - public File getBuiltinCudaLib() { - return cudalibFolder.get(); + private void updateLastUsedAndCleanupStaleVersions(File resourceFolder, File includesFolder) { + var now = Instant.now(); + touchUse(resourceFolder, includesFolder); + deleteStaleVersions(now, resourceFolder, includesFolder); } - private File prepareBuiltinCudaLib() { - var fileResource = CLANG_AST_RESOURCES.get(ClangAstFileResource.CUDA_LIB); - var resourceFolder = getClangResourceFolder(); - var cudalibFolder = SpecsIo.mkdir(new File(resourceFolder, "cudalib")); + void deleteStaleVersions(Instant now, File currentVersionFolder) { + deleteStaleVersions(now, currentVersionFolder, null); + } - // Download includes zips, check if any of them is new - ResourceWriteData zipFile = fileResource.writeVersioned(resourceFolder, ClangResources.class); + private void deleteStaleVersions(Instant now, File currentVersionFolder, File currentIncludesFolder) { + var cutoff = now.minus(STALE_CACHE_MAX_AGE); + var cacheRoot = getClangCacheRoot().toPath(); + try { + CacheFiles.deleteStaleDirectories(cacheRoot, getReleasesFolder().toPath(), cutoff, + currentVersionFolder.toPath()); + CacheFiles.deleteStaleDirectories(cacheRoot, getIncludesRoot().toPath(), cutoff, + currentIncludesFolder == null ? null : currentIncludesFolder.toPath()); + CacheFiles.deleteUnlockedStagingLocks(cacheRoot, currentVersionFolder.toPath()); + CacheFiles.deleteUnlockedStagingLocks(cacheRoot, getIncludesRoot().toPath()); + } catch (RuntimeException e) { + SpecsLogs.warn("Could not clean stale clang-dumper cache resources", e); + } + } + + private static String getManifestPlatform() { + var platform = SupportedPlatform.getCurrentPlatform(); + + if (platform.isLinux()) { + return "linux"; + } + + if (platform.isMacOs()) { + return "macos"; + } + + if (platform.isWindows()) { + return "windows"; + } + + throw new RuntimeException("Unsupported platform: " + platform); + } - // If a new file has been written, delete includes folder, and extract all zips again - // Extracting all because zips might have several folders and we are not determining which should be updated - if (zipFile.isNewFile()) { - // Clean folder - SpecsIo.deleteFolderContents(cudalibFolder); + private static String getManifestArch(String platform) { + var osArch = System.getProperty("os.arch").toLowerCase(); + + if (osArch.equals("amd64") || osArch.equals("x86_64")) { + return platform.equals("windows") ? "x86_64" : "x64"; + } - // Extract zip - SpecsIo.extractZip(zipFile.getFile(), cudalibFolder); + if (osArch.equals("aarch64") || osArch.equals("arm64")) { + return "arm64"; } - // Returnb cuda lib folder - return cudalibFolder; + throw new RuntimeException("Unsupported architecture for clang-dumper: " + osArch); + } + + private record PreparedIncludes(List folders, File extractedFolder) { + } + + private record CachedClangFiles(ClangFiles files, File includesFolder) { } } diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/CudaResources.java b/ClangAstParser/src/pt/up/fe/specs/clang/CudaResources.java new file mode 100644 index 0000000000..93afe53dd5 --- /dev/null +++ b/ClangAstParser/src/pt/up/fe/specs/clang/CudaResources.java @@ -0,0 +1,805 @@ +/** + * Copyright 2026 SPeCS. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; +import pt.up.fe.specs.util.SpecsIo; +import pt.up.fe.specs.util.SpecsLogs; +import pt.up.fe.specs.util.providers.FileResourceProvider; +import pt.up.fe.specs.util.providers.WebResourceProvider; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Pattern; + +/** + * Downloads the NVIDIA redistribution packages required by Clang and assembles them into the CUDA root expected by + * the bundled dumper. + * + *

CUDA resources are release-addressed. Archives from different CUDA releases therefore never share a cache + * destination, even when NVIDIA publishes identical bytes for both releases.

+ */ +final class CudaResources { + + static final String NVIDIA_REDIST_ROOT = "https://developer.download.nvidia.com/compute/cuda/redist/"; + static final List REQUIRED_COMPONENTS = List.of("cuda_cudart", "cuda_nvcc", "libcurand", "cuda_cccl"); + static final String PLATFORM_FILENAME = ".platform"; + + private static final String CUDA_FOLDERNAME = "cuda"; + private static final String CUDA_LIB_FOLDERNAME = "cudalib"; + private static final String ARCHIVES_FOLDERNAME = "archives"; + private static final String MANIFEST_FILENAME_PREFIX = "redistrib_"; + private static final String MANIFEST_FILENAME_SUFFIX = ".json"; + private static final Set MANIFEST_FIELDS = Set.of("release_date", "release_label", "release_product"); + private static final Set COMPONENT_FIELDS = Set.of("name", "license", "license_path", "version"); + private static final Pattern SHA256_PATTERN = Pattern.compile("[0-9a-fA-F]{64}"); + private static final List REQUIRED_FILES = List.of( + "include/cuda.h", + "include/cuda_runtime.h", + "include/texture_fetch_functions.h", + "include/curand_mtgp32_kernel.h", + "include/nv/target", + "include/crt/host_config.h", + "nvvm/libdevice/libdevice.10.bc"); + + private CudaResources() { + } + + static File getBuiltinCudaLib(Path cacheRoot) { + var releaseTag = ClangAstWebResource.getCudaReleaseTag(); + var releaseFolder = getReleaseFolder(cacheRoot, releaseTag); + claimReleaseInUse(cacheRoot, releaseFolder); + var manifest = getManifest(cacheRoot, releaseFolder); + var platform = requireSupportedPlatform(manifest); + var platformFolder = getPlatformFolder(cacheRoot, releaseTag, platform); + var installationFolder = getInstallationFolder(platformFolder); + + // A published installation is immutable. A malformed one is an operator error, not an invitation to repair it + // in place, because doing so could race with a reader that already selected this release. + if (Files.exists(installationFolder.toPath(), LinkOption.NOFOLLOW_LINKS)) { + return useExistingInstallation(cacheRoot, platformFolder, platform, installationFolder); + } + + claimInUse(cacheRoot, platformFolder); + return install(cacheRoot, platformFolder, releaseTag, platform, manifest, CudaResources::getArchiveResource); + } + + private static void claimReleaseInUse(Path cacheRoot, File releaseFolder) { + CacheFiles.withMaintenanceLock(cacheRoot, () -> { + try { + Files.createDirectories(releaseFolder.toPath()); + } catch (IOException e) { + throw new UncheckedIOException("Could not create CUDA release folder '" + releaseFolder + "'", e); + } + + CacheFiles.touch(releaseFolder.toPath()); + }); + } + + static void claimInUse(Path cacheRoot, File platformFolder) { + CacheFiles.withMaintenanceLock(cacheRoot, () -> { + var platformPath = platformFolder.toPath(); + var releasePath = platformPath.getParent(); + if (releasePath == null) { + throw new RuntimeException("CUDA platform folder is not below a release folder: '" + + platformFolder + "'"); + } + + try { + Files.createDirectories(platformPath); + } catch (IOException e) { + throw new UncheckedIOException("Could not create CUDA platform folder '" + platformPath + "'", e); + } + + CacheFiles.touch(releasePath); + CacheFiles.touch(platformPath); + }); + } + + static CudaPlatform requireSupportedPlatform() { + return getCurrentPlatform(); + } + + static CudaPlatform requireSupportedPlatform(NvidiaCudaManifest manifest) { + var platform = SupportedPlatform.getCurrentPlatform(); + var architecture = System.getProperty("os.arch"); + return findSupportedPlatform(manifest) + .orElseThrow(() -> unsupportedPlatform(manifest, platform, architecture)); + } + + static boolean isSupportedPlatform() { + return isSupportedPlatform(ClangResources.getDefaultTempFolder().toPath()); + } + + static boolean isSupportedPlatform(Path cacheRoot) { + return findSupportedPlatform(getCurrentManifest(cacheRoot)).isPresent(); + } + + static CudaPlatform getCurrentPlatform() { + return getCurrentPlatform(ClangResources.getDefaultTempFolder().toPath()); + } + + static CudaPlatform getCurrentPlatform(Path cacheRoot) { + return requireSupportedPlatform(getCurrentManifest(cacheRoot)); + } + + static CudaPlatform getCurrentPlatform(NvidiaCudaManifest manifest) { + return requireSupportedPlatform(manifest); + } + + static String getManifestPlatform(NvidiaCudaManifest manifest, SupportedPlatform platform, String architecture) { + return findManifestPlatform(manifest, platform, architecture) + .orElseThrow(() -> unsupportedPlatform(manifest, platform, architecture)); + } + + private static Optional findSupportedPlatform(NvidiaCudaManifest manifest) { + return findManifestPlatform(manifest, SupportedPlatform.getCurrentPlatform(), + System.getProperty("os.arch")).map(CudaPlatform::new); + } + + private static Optional findManifestPlatform(NvidiaCudaManifest manifest, SupportedPlatform platform, + String architecture) { + Objects.requireNonNull(manifest, "manifest"); + Objects.requireNonNull(platform, "platform"); + Objects.requireNonNull(architecture, "architecture"); + + var commonPlatforms = new LinkedHashSet(); + var missingComponents = new ArrayList(); + var firstComponent = true; + for (var componentName : REQUIRED_COMPONENTS) { + var component = manifest.components().get(componentName); + if (component == null) { + missingComponents.add(componentName); + continue; + } + + if (firstComponent) { + commonPlatforms.addAll(component.archives().keySet()); + firstComponent = false; + } else { + commonPlatforms.retainAll(component.archives().keySet()); + } + } + + if (!missingComponents.isEmpty()) { + throw new RuntimeException("NVIDIA CUDA manifest is missing required components " + missingComponents + + ". Available manifest platform keys: " + getAvailablePlatformKeys(manifest)); + } + + return commonPlatforms.stream() + .filter(candidate -> isCompatiblePlatform(candidate, platform, architecture)) + .findFirst(); + } + + private static RuntimeException unsupportedPlatform(NvidiaCudaManifest manifest, SupportedPlatform platform, + String architecture) { + return new RuntimeException("Built-in CUDA is unsupported for host '" + platform + " (" + architecture + + ")': no platform key is present in all required components and is compatible with this host" + + ". Available manifest platform keys: " + getAvailablePlatformKeys(manifest)); + } + + private static NvidiaCudaManifest getCurrentManifest(Path cacheRoot) { + var releaseTag = ClangAstWebResource.getCudaReleaseTag(); + var releaseFolder = getReleaseFolder(cacheRoot, releaseTag); + claimReleaseInUse(cacheRoot, releaseFolder); + return getManifest(cacheRoot, releaseFolder); + } + + private static boolean isCompatiblePlatform(String manifestPlatform, SupportedPlatform hostPlatform, + String hostArchitecture) { + var separator = manifestPlatform.indexOf('-'); + if (separator <= 0 || separator == manifestPlatform.length() - 1) { + return false; + } + + var manifestOs = normalizeOs(manifestPlatform.substring(0, separator)); + var manifestArchitecture = normalizeArchitecture(manifestPlatform.substring(separator + 1)); + return manifestOs.equals(normalizeOs(hostPlatform)) + && manifestArchitecture.equals(normalizeArchitecture(hostArchitecture)); + } + + private static String normalizeOs(SupportedPlatform platform) { + return switch (platform) { + case WINDOWS -> "windows"; + case LINUX -> "linux"; + case MAC_OS -> "macos"; + }; + } + + private static String normalizeOs(String os) { + var normalized = os.toLowerCase(Locale.ROOT).replace("_", "").replace("-", ""); + return switch (normalized) { + case "darwin", "mac" -> "macos"; + default -> normalized; + }; + } + + private static String normalizeArchitecture(String architecture) { + var normalized = architecture.toLowerCase(Locale.ROOT).replace("_", "").replace("-", ""); + return switch (normalized) { + case "amd64", "x8664", "x64" -> "x8664"; + case "aarch64", "arm64", "armv8", "armv8l", "sbsa" -> "arm64"; + default -> normalized; + }; + } + + private static Map> getAvailablePlatformKeys(NvidiaCudaManifest manifest) { + var available = new LinkedHashMap>(); + for (var componentName : REQUIRED_COMPONENTS) { + var component = manifest.components().get(componentName); + var platforms = component == null ? List.of() : component.archives().keySet().stream().sorted().toList(); + available.put(componentName, platforms); + } + + return available; + } + + private static File getReleaseFolder(Path cacheRoot, String releaseTag) { + return cacheRoot.resolve(CUDA_FOLDERNAME).resolve(releaseTag).toFile(); + } + + static File getPlatformFolder(Path cacheRoot, String releaseTag, CudaPlatform platform) { + return getReleaseFolder(cacheRoot, releaseTag).toPath().resolve(platform.manifestName()).toFile(); + } + + static File getInstallationFolder(File platformFolder) { + return new File(platformFolder, CUDA_LIB_FOLDERNAME); + } + + static File getArchiveFile(File platformFolder, CudaPackage cudaPackage) { + var relativePath = cudaPackage.archive().relativePath(); + var archiveName = relativePath.substring(relativePath.lastIndexOf('/') + 1); + return new File(new File(new File(platformFolder, ARCHIVES_FOLDERNAME), cudaPackage.component()), archiveName); + } + + static NvidiaCudaManifest getManifest(File resourceFolder) { + return getManifest(getCacheRoot(resourceFolder), resourceFolder); + } + + static NvidiaCudaManifest getManifest(Path cacheRoot, File resourceFolder) { + var releaseTag = ClangAstWebResource.getCudaReleaseTag(); + var manifestFilename = getManifestFilename(releaseTag); + var resource = WebResourceProvider.newInstance(NVIDIA_REDIST_ROOT, manifestFilename, releaseTag); + var manifestFile = CacheFiles.installFile(cacheRoot, new File(resourceFolder, manifestFilename), resource, null, + "NVIDIA CUDA redistribution manifest"); + var manifest = parseManifest(SpecsIo.read(manifestFile)); + validateManifest(manifest, releaseTag); + return manifest; + } + + private static Path getCacheRoot(File resourceFolder) { + var cacheRoot = resourceFolder.toPath(); + for (int i = 0; i < 3; i++) { + cacheRoot = cacheRoot.getParent(); + if (cacheRoot == null) { + throw new RuntimeException("CUDA resource folder is not below a cache root: '" + resourceFolder + "'"); + } + } + + return cacheRoot; + } + + static String getManifestFilename(String releaseTag) { + return MANIFEST_FILENAME_PREFIX + releaseTag + MANIFEST_FILENAME_SUFFIX; + } + + static WebResourceProvider getArchiveResource(CudaPackage cudaPackage) { + var archive = cudaPackage.archive(); + return WebResourceProvider.newInstance(NVIDIA_REDIST_ROOT, archive.relativePath(), + "cuda-" + cudaPackage.component() + "-" + archive.sha256()); + } + + static NvidiaCudaManifest parseManifest(String json) { + if (json == null || json.isBlank()) { + throw new RuntimeException("NVIDIA CUDA redistribution manifest is empty"); + } + + final JsonObject root; + try { + root = JsonParser.parseString(json).getAsJsonObject(); + } catch (RuntimeException e) { + throw new RuntimeException("Could not parse NVIDIA CUDA redistribution manifest", e); + } + + var releaseDate = getRequiredString(root, "release_date", "manifest"); + var releaseLabel = getRequiredString(root, "release_label", "manifest"); + var releaseProduct = getRequiredString(root, "release_product", "manifest"); + var components = new LinkedHashMap(); + + for (var entry : root.entrySet()) { + if (MANIFEST_FIELDS.contains(entry.getKey())) { + continue; + } + + if (!entry.getValue().isJsonObject()) { + throw new RuntimeException("NVIDIA CUDA manifest component '" + entry.getKey() + + "' is not an object"); + } + + components.put(entry.getKey(), parseComponent(entry.getKey(), entry.getValue().getAsJsonObject())); + } + + if (components.isEmpty()) { + throw new RuntimeException("NVIDIA CUDA redistribution manifest does not contain components"); + } + + return new NvidiaCudaManifest(releaseDate, releaseLabel, releaseProduct, components); + } + + static File install(Path cacheRoot, File resourceFolder, String releaseTag, CudaPlatform platform, + NvidiaCudaManifest manifest, + Function archiveResourceFactory) { + validateManifest(manifest, releaseTag); + Objects.requireNonNull(archiveResourceFactory, "archiveResourceFactory"); + + var installationFolder = getInstallationFolder(resourceFolder); + if (Files.exists(installationFolder.toPath(), LinkOption.NOFOLLOW_LINKS)) { + return useExistingInstallation(cacheRoot, resourceFolder, platform, installationFolder); + } + + var downloadedPackages = manifest.getRequiredPackages(platform.manifestName()).stream() + .map(cudaPackage -> downloadPackage(cacheRoot, resourceFolder, cudaPackage, archiveResourceFactory)) + .toList(); + + CacheFiles.deleteUnlockedStagingLocks(cacheRoot, resourceFolder.toPath()); + var stagingDirectory = CacheFiles.createStagingDirectory(cacheRoot, resourceFolder.toPath(), ".cudalib.tmp-"); + try { + try { + assemble(stagingDirectory.path().toFile(), platform, downloadedPackages); + } catch (IOException e) { + throw new UncheckedIOException("Could not assemble CUDA resources in '" + + stagingDirectory.path() + "'", e); + } + + if (!isCudaInstallation(stagingDirectory.path().toFile(), platform.manifestName())) { + throw new RuntimeException("Assembled CUDA resources failed structural validation in '" + + stagingDirectory.path() + "'"); + } + + var publishedFolder = CacheFiles.publish(stagingDirectory.path(), installationFolder.toPath()).toFile(); + return useExistingInstallation(cacheRoot, resourceFolder, platform, publishedFolder); + } finally { + try { + CacheFiles.delete(stagingDirectory.path()); + } finally { + stagingDirectory.close(); + } + } + } + + private static CudaResources.DownloadedPackage downloadPackage(Path cacheRoot, File resourceFolder, + CudaPackage cudaPackage, + Function factory) { + var destination = getArchiveFile(resourceFolder, cudaPackage); + var archiveParent = destination.getParentFile().toPath(); + CacheFiles.deleteUnlockedStagingLocks(cacheRoot, archiveParent); + var archive = CacheFiles.installFile(cacheRoot, destination, factory.apply(cudaPackage), + cudaPackage.archive().sha256(), cudaPackage.archive().size(), + "NVIDIA CUDA archive '" + destination.getName() + "'"); + return new DownloadedPackage(cudaPackage, archive); + } + + private static File useExistingInstallation(Path cacheRoot, File resourceFolder, CudaPlatform platform, + File installationFolder) { + var validInstallation = CacheFiles.withMaintenanceLock(cacheRoot, () -> { + if (!isCudaInstallation(installationFolder, platform.manifestName())) { + throw invalidInstallation(installationFolder, platform.manifestName()); + } + + CacheFiles.touch(resourceFolder.toPath()); + CacheFiles.touch(resourceFolder.getParentFile().toPath()); + return installationFolder; + }); + + cleanup(cacheRoot, resourceFolder); + SpecsLogs.debug(() -> "Using cached CUDA resources: " + validInstallation); + return validInstallation; + } + + private static void cleanup(Path cacheRoot, File resourceFolder) { + var cudaRoot = cacheRoot.resolve(CUDA_FOLDERNAME); + var releaseFolder = resourceFolder.toPath().getParent(); + var cutoff = Instant.now().minus(Duration.ofDays(60)); + try { + CacheFiles.deleteStaleDirectories(cacheRoot, cudaRoot, cutoff, releaseFolder); + CacheFiles.deleteUnlockedStagingLocks(cacheRoot, releaseFolder); + CacheFiles.deleteUnlockedStagingLocks(cacheRoot, resourceFolder.toPath()); + for (var component : REQUIRED_COMPONENTS) { + CacheFiles.deleteUnlockedStagingLocks(cacheRoot, + resourceFolder.toPath().resolve(ARCHIVES_FOLDERNAME).resolve(component)); + } + } catch (RuntimeException e) { + SpecsLogs.warn("Could not clean stale CUDA cache resources", e); + } + } + + static boolean isCudaInstallation(File folder, String platform) { + Path root = folder.toPath().toAbsolutePath().normalize(); + if (!Files.isDirectory(root, LinkOption.NOFOLLOW_LINKS) + || !Files.isDirectory(root.resolve("bin"), LinkOption.NOFOLLOW_LINKS)) { + return false; + } + + for (var requiredFile : REQUIRED_FILES) { + if (!Files.isRegularFile(root.resolve(requiredFile), LinkOption.NOFOLLOW_LINKS)) { + return false; + } + } + + var platformFile = root.resolve(PLATFORM_FILENAME); + if (!Files.isRegularFile(platformFile, LinkOption.NOFOLLOW_LINKS)) { + return false; + } + + try { + return platform.equals(Files.readString(platformFile).trim()); + } catch (IOException e) { + return false; + } + } + + private static RuntimeException invalidInstallation(File folder, String platform) { + return new RuntimeException("Invalid published CUDA installation '" + folder.getAbsolutePath() + + "' for platform '" + platform + "'; delete this directory manually to regenerate"); + } + + private static void validateManifest(NvidiaCudaManifest manifest, String releaseTag) { + Objects.requireNonNull(manifest, "manifest"); + if (!releaseTag.equals(manifest.releaseLabel())) { + throw new RuntimeException("NVIDIA CUDA manifest release label '" + manifest.releaseLabel() + + "' does not match the configured CUDA release tag '" + releaseTag + "'"); + } + + if (!"cuda".equals(manifest.releaseProduct())) { + throw new RuntimeException("NVIDIA redistribution manifest is not a CUDA manifest: '" + + manifest.releaseProduct() + "'"); + } + } + + private static NvidiaCudaComponent parseComponent(String componentName, JsonObject component) { + var name = getRequiredString(component, "name", "component '" + componentName + "'"); + var version = getRequiredString(component, "version", "component '" + componentName + "'"); + var archives = new LinkedHashMap(); + + for (var entry : component.entrySet()) { + if (COMPONENT_FIELDS.contains(entry.getKey())) { + continue; + } + + if (!entry.getValue().isJsonObject()) { + continue; + } + + var platform = entry.getKey(); + var platformObject = entry.getValue().getAsJsonObject(); + var relativePath = getRequiredString(platformObject, "relative_path", + "component '" + componentName + "', platform '" + platform + "'"); + var sha256 = getRequiredString(platformObject, "sha256", + "component '" + componentName + "', platform '" + platform + "'"); + validateSha256(sha256, componentName, platform); + var size = getRequiredLong(platformObject, "size", + "component '" + componentName + "', platform '" + platform + "'"); + validateRelativePath(relativePath, "component '" + componentName + "', platform '" + platform + "'"); + if (size < 0) { + throw new RuntimeException("NVIDIA CUDA archive size must not be negative for component '" + + componentName + "', platform '" + platform + "'"); + } + + archives.put(platform, new CudaArchive(relativePath, sha256, size)); + } + + if (archives.isEmpty()) { + throw new RuntimeException("NVIDIA CUDA component '" + componentName + "' has no platform archives"); + } + + return new NvidiaCudaComponent(name, version, archives); + } + + private static String getRequiredString(JsonObject object, String field, String owner) { + JsonElement value = object.get(field); + if (value == null || value.isJsonNull() || !value.isJsonPrimitive() + || !value.getAsJsonPrimitive().isString()) { + throw new RuntimeException("NVIDIA CUDA " + owner + " is missing string field '" + field + "'"); + } + + var stringValue = value.getAsString().trim(); + if (stringValue.isEmpty()) { + throw new RuntimeException("NVIDIA CUDA " + owner + " has an empty field '" + field + "'"); + } + + return stringValue; + } + + private static long getRequiredLong(JsonObject object, String field, String owner) { + JsonElement value = object.get(field); + if (value == null || value.isJsonNull() || !value.isJsonPrimitive()) { + throw new RuntimeException("NVIDIA CUDA " + owner + " is missing numeric field '" + field + "'"); + } + + try { + return value.getAsLong(); + } catch (RuntimeException e) { + throw new RuntimeException("NVIDIA CUDA " + owner + " has an invalid numeric field '" + field + "'", e); + } + } + + private static void validateSha256(String sha256, String component, String platform) { + if (!SHA256_PATTERN.matcher(sha256).matches()) { + throw new RuntimeException("NVIDIA CUDA archive for component '" + component + "', platform '" + + platform + "' has an invalid SHA-256: '" + sha256 + "'"); + } + } + + private static void validateRelativePath(String relativePath, String owner) { + if (relativePath.startsWith("/") || relativePath.startsWith("\\") || relativePath.contains("\\") + || hasWindowsDrivePrefix(relativePath)) { + throw new RuntimeException("NVIDIA CUDA " + owner + " has an unsafe relative path: '" + relativePath + "'"); + } + + for (var segment : relativePath.split("/", -1)) { + if (segment.isEmpty() || segment.equals(".") || segment.equals("..")) { + throw new RuntimeException("NVIDIA CUDA " + owner + " has an unsafe relative path: '" + relativePath + "'"); + } + } + } + + static void assemble(File stagingFolder, CudaPlatform platform, List packages) throws IOException { + Files.writeString(new File(stagingFolder, PLATFORM_FILENAME).toPath(), platform.manifestName()); + Files.createDirectories(new File(stagingFolder, "bin").toPath()); + + for (var downloadedPackage : packages) { + var component = downloadedPackage.cudaPackage().component(); + var sourceRoots = switch (component) { + case "cuda_cudart", "libcurand", "cuda_cccl" -> List.of("include"); + case "cuda_nvcc" -> List.of("include/crt", "nvvm/libdevice/libdevice.10.bc"); + default -> throw new RuntimeException("Unsupported NVIDIA CUDA component '" + component + "'"); + }; + + extractArchive(downloadedPackage.archiveFile(), stagingFolder, sourceRoots); + } + } + + private static void extractArchive(File archive, File destination, List sourceRoots) throws IOException { + if (archive.getName().endsWith(".zip")) { + try (InputStream input = Files.newInputStream(archive.toPath()); + var archiveInput = new ZipArchiveInputStream(input)) { + extractArchiveEntries(archiveInput, archive, destination, sourceRoots, + entry -> entry instanceof ZipArchiveEntry zipEntry && isRegularZipEntry(zipEntry)); + } + return; + } + + if (!archive.getName().endsWith(".tar.xz")) { + throw new RuntimeException("Unsupported NVIDIA CUDA archive format: '" + archive + "'"); + } + + try (InputStream input = Files.newInputStream(archive.toPath()); + var xzInput = new XZCompressorInputStream(input); + var tarInput = new TarArchiveInputStream(xzInput)) { + extractArchiveEntries(tarInput, archive, destination, sourceRoots, + entry -> entry instanceof TarArchiveEntry tarEntry && tarEntry.isFile()); + } + } + + private static void extractArchiveEntries(ArchiveInputStream archiveInput, File archive, File destination, + List sourceRoots, ArchiveEntryPolicy entryPolicy) throws IOException { + var foundRoots = new HashSet(); + String archiveRoot = null; + ArchiveEntry entry; + while ((entry = archiveInput.getNextEntry()) != null) { + var entryName = validateArchiveEntryName(entry.getName(), archive); + var topLevel = getTopLevelPath(entryName); + + if (archiveRoot == null) { + archiveRoot = topLevel; + } else if (!archiveRoot.equals(topLevel)) { + throw new RuntimeException("NVIDIA CUDA archive contains multiple top-level folders: '" + + archiveRoot + "' and '" + topLevel + "'"); + } + + var relativeName = entryName.length() == archiveRoot.length() + ? "" + : entryName.substring(archiveRoot.length() + 1); + var sourceRoot = findSourceRoot(relativeName, sourceRoots); + if (sourceRoot == null) { + continue; + } + + if (!entry.isDirectory() && !entryPolicy.isRegular(entry)) { + throw new RuntimeException("NVIDIA CUDA archive contains a non-regular selected entry: '" + + entryName + "'"); + } + + if (entry.isDirectory()) { + Files.createDirectories(destination.toPath().resolve(relativeName)); + continue; + } + + foundRoots.add(sourceRoot); + copyArchiveFile(archiveInput, destination.toPath().resolve(relativeName), entryName); + } + + if (!foundRoots.containsAll(sourceRoots)) { + var missingRoots = new ArrayList<>(sourceRoots); + missingRoots.removeAll(foundRoots); + throw new RuntimeException("NVIDIA CUDA archive '" + archive + "' is missing selected paths: " + missingRoots); + } + } + + private static boolean isRegularZipEntry(ZipArchiveEntry entry) { + if (entry.isUnixSymlink()) { + return false; + } + + var unixMode = entry.getUnixMode(); + return unixMode == 0 || (unixMode & 0170000) == 0100000; + } + + private static String validateArchiveEntryName(String entryName, File archive) { + if (entryName == null || entryName.isBlank() || entryName.startsWith("/") || entryName.contains("\\") + || hasWindowsDrivePrefix(entryName)) { + throw new RuntimeException("NVIDIA CUDA archive '" + archive + "' contains an unsafe path: '" + entryName + "'"); + } + + var normalizedName = entryName.endsWith("/") ? entryName.substring(0, entryName.length() - 1) : entryName; + if (normalizedName.isEmpty()) { + throw new RuntimeException("NVIDIA CUDA archive '" + archive + "' contains an empty path"); + } + + for (var segment : normalizedName.split("/", -1)) { + if (segment.isEmpty() || segment.equals(".") || segment.equals("..")) { + throw new RuntimeException("NVIDIA CUDA archive '" + archive + "' contains an unsafe path: '" + entryName + "'"); + } + } + + return normalizedName; + } + + private static boolean hasWindowsDrivePrefix(String path) { + return path.length() >= 2 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':'; + } + + private static String getTopLevelPath(String entryName) { + var separator = entryName.indexOf('/'); + return separator == -1 ? entryName : entryName.substring(0, separator); + } + + private static String findSourceRoot(String relativeName, List sourceRoots) { + for (var sourceRoot : sourceRoots) { + if (relativeName.equals(sourceRoot) || relativeName.startsWith(sourceRoot + "/")) { + return sourceRoot; + } + } + + return null; + } + + private static void copyArchiveFile(InputStream input, Path destination, String entryName) throws IOException { + Files.createDirectories(destination.getParent()); + var temporaryFile = Files.createTempFile(destination.getParent(), ".cuda-entry-", ".tmp"); + try { + try (OutputStream output = Files.newOutputStream(temporaryFile)) { + input.transferTo(output); + } + + if (Files.exists(destination, LinkOption.NOFOLLOW_LINKS)) { + if (!Files.isRegularFile(destination, LinkOption.NOFOLLOW_LINKS) + || Files.mismatch(destination, temporaryFile) != -1) { + throw new RuntimeException("NVIDIA CUDA archives contain conflicting files at '" + entryName + "'"); + } + return; + } + + try { + Files.move(temporaryFile, destination, StandardCopyOption.ATOMIC_MOVE); + } catch (java.nio.file.AtomicMoveNotSupportedException e) { + Files.move(temporaryFile, destination); + } catch (java.nio.file.FileAlreadyExistsException e) { + if (!Files.isRegularFile(destination, LinkOption.NOFOLLOW_LINKS) + || Files.mismatch(destination, temporaryFile) != -1) { + throw new RuntimeException("NVIDIA CUDA archives contain conflicting files at '" + entryName + "'"); + } + } + } finally { + Files.deleteIfExists(temporaryFile); + } + } + + record NvidiaCudaManifest(String releaseDate, String releaseLabel, String releaseProduct, + Map components) { + + NvidiaCudaManifest { + components = Map.copyOf(components); + } + + List getRequiredPackages(String platform) { + return REQUIRED_COMPONENTS.stream() + .map(component -> new CudaPackage(component, getComponent(component).getArchive(platform))) + .toList(); + } + + private NvidiaCudaComponent getComponent(String component) { + var value = components.get(component); + if (value == null) { + throw new RuntimeException("NVIDIA CUDA manifest is missing required component '" + component + "'"); + } + + return value; + } + } + + record NvidiaCudaComponent(String name, String version, Map archives) { + + NvidiaCudaComponent { + archives = Map.copyOf(archives); + } + + CudaArchive getArchive(String platform) { + var archive = archives.get(platform); + if (archive == null) { + throw new RuntimeException("NVIDIA CUDA component '" + name + "' has no archive for platform '" + + platform + "'"); + } + + return archive; + } + } + + record CudaPackage(String component, CudaArchive archive) { + } + + record CudaArchive(String relativePath, String sha256, long size) { + } + + record DownloadedPackage(CudaPackage cudaPackage, File archiveFile) { + } + + record CudaPlatform(String manifestName) { + } + + @FunctionalInterface + private interface ArchiveEntryPolicy { + + boolean isRegular(ArchiveEntry entry); + } +} diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/SupportedPlatform.java b/ClangAstParser/src/pt/up/fe/specs/clang/SupportedPlatform.java index 094c8662e6..0564571a84 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/SupportedPlatform.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/SupportedPlatform.java @@ -74,10 +74,6 @@ private static SupportedPlatform calculateCurrentPlatform() { // Linux if (SpecsPlatforms.isLinux()) { - if (SpecsPlatforms.isLinuxArm()) { - throw new RuntimeException("ARM-based platforms are not currently supported"); - } - return LINUX; } diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/CodeParser.java b/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/CodeParser.java index 5c154cd24e..e65c941a94 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/CodeParser.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/CodeParser.java @@ -45,7 +45,7 @@ public abstract class CodeParser extends ADataClass { .setLabel("CUDA Path (empty: uses system installed; : uses builtin version)") .setDefaultString(""); public static final DataKey DUMPER_FOLDER = KeyFactory.folder("dumperFolder") - .setLabel("The work folder for the clang-dumper. Clava will look for it in this folder, and if not found, will download it. If not set, a temporary folder will be used.") + .setLabel("The base cache folder for Clava's downloaded resources. Clava stores each clang-dumper and CUDA release in a versioned subfolder and downloads it if not found. If not set, a temporary folder will be used.") .setDefault(ClangResources::getDefaultTempFolder); /** diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/ParallelCodeParser.java b/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/ParallelCodeParser.java index 399d916211..91b7ca5b98 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/ParallelCodeParser.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/codeparser/ParallelCodeParser.java @@ -18,7 +18,6 @@ import org.suikasoft.jOptions.Interfaces.DataStore; import pt.up.fe.specs.clang.ClangAstKeys; import pt.up.fe.specs.clang.ClangResources; -import pt.up.fe.specs.clang.LibcMode; import pt.up.fe.specs.clang.dumper.ClangAstData; import pt.up.fe.specs.clang.dumper.ClangAstDumper; import pt.up.fe.specs.clang.dumper.ClangAstParser; @@ -104,20 +103,13 @@ public App parse(List inputSources, List compilerOptions, ClavaCon // Standard standard = getStandard(allUserSources.values(), options); // config.getTry(ClavaOptions.STANDARD).ifPresent(standard -> arguments.add(standard.getFlag())); - // Get version for the executable - String version = options.get(ClangAstKeys.CLANGAST_VERSION); // System.out.println("PARALLEL OPTIONS: " + options); // Prepare resources before execution // ClangResources clangResources = new ClangResources(get(SHOW_CLANG_DUMP)); ClangResources clangResources = new ClangResources(this); - - if (ClangAstDumper.usePlugin()) { - set(ClangAstKeys.LIBC_CXX_MODE, LibcMode.SYSTEM); - ClavaLog.debug(() -> "In Linux, ClangAstDumper is a plugin. LIBC_CXX_MODE is reset to SYSTEM."); - } - - var clangFiles = clangResources.getClangFiles(version, get(ClangAstKeys.LIBC_CXX_MODE)); + var clangFiles = clangResources.getClangFiles(get(ClangAstKeys.LIBC_CXX_MODE)); + options.set(ClangAstKeys.LIBC_CXX_MODE, clangFiles.libcMode()); // File clangExecutable = clangResources.prepareResources(version); // List builtinIncludes = clangResources.prepareIncludes(clangExecutable, // get(ClangAstKeys.USE_PLATFORM_INCLUDES)); @@ -147,7 +139,8 @@ public App parse(List inputSources, List compilerOptions, ClavaCon Future tUnit = executor .submit(() -> parseSource(source, id, standard, options, clangDump, - counter, parsingFolder, clangFiles.clangExecutable(), clangFiles.builtinIncludes())); + counter, parsingFolder, clangFiles.clangExecutable(), clangFiles.builtinIncludes(), + clangFiles.systemResourceDir())); futureTUnits.add(tUnit); @@ -246,7 +239,9 @@ public App parse(List inputSources, List compilerOptions, ClavaCon app.getContext().pushApp(app); app.setSourcesFromStrings(allSources); - app.addConfig(ClangAstKeys.toDataStore(compilerOptions)); + DataStore appConfig = ClangAstKeys.toDataStore(compilerOptions); + appConfig.set(ClangAstKeys.LIBC_CXX_MODE, clangFiles.libcMode()); + app.addConfig(appConfig); // Applies several passes to make the tree resemble more the original code, e.g., remove implicit nodes from // original clang tree @@ -364,7 +359,7 @@ private Standard getStandard(Collection sources, DataStore options) { private ClangAstData parseSource(File sourceFile, String id, Standard standard, DataStore options, ConcurrentLinkedQueue clangDump, ParallelProgressCounter counter, File parsingFolder, - File clangExecutable, List builtinIncludes) { + File clangExecutable, List builtinIncludes, File systemResourceDir) { // ConcurrentLinkedQueue clangDump, ConcurrentLinkedQueue workingFolders) { @@ -376,7 +371,7 @@ private ClangAstData parseSource(File sourceFile, String id, Standard standard, boolean streamConsoleOutput = !get(PARALLEL_PARSING); ClangAstDumper clangParser = new ClangAstDumper(streamConsoleOutput, clangExecutable, builtinIncludes, - this) + systemResourceDir, this) .setBaseFolder(parsingFolder) .setSystemIncludesThreshold(get(SYSTEM_INCLUDES_THRESHOLD)); diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstDumper.java b/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstDumper.java index 0a319a6d89..b0c1463f08 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstDumper.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstDumper.java @@ -18,6 +18,7 @@ import org.suikasoft.jOptions.streamparser.LineStreamParser; import pt.up.fe.specs.clang.ClangAstKeys; import pt.up.fe.specs.clang.ClangResources; +import pt.up.fe.specs.clang.LibcMode; import pt.up.fe.specs.clang.cilk.CilkParser; import pt.up.fe.specs.clang.codeparser.CodeParser; import pt.up.fe.specs.clang.codeparser.ParallelCodeParser; @@ -52,6 +53,7 @@ public class ClangAstDumper { private final static boolean USE_PLUGIN = false; + private final static String SYSTEM_HEADER_THRESHOLD_OPTION = "-system-header-threshold="; public static boolean usePlugin() { return USE_PLUGIN; @@ -60,7 +62,7 @@ public static boolean usePlugin() { private final static String CLANG_DUMP_FILENAME = "clangDump.txt"; private final static String STDERR_DUMP_FILENAME = "stderr.txt"; - private static final List CLANG_AST_DUMPER_TEMP_FILES = Arrays.asList("includes.txt", CLANG_DUMP_FILENAME, + private static final List CLANG_AST_DUMPER_TEMP_FILES = List.of("includes.txt", CLANG_DUMP_FILENAME, // "clavaDump.txt", "nodetypes.txt", "types.txt", "is_temporary.txt", "template_args.txt", "clavaDump.txt", "nodetypes.txt", "types.txt", "is_temporary.txt", "omp.txt", "invalid_source.txt", "enum_integer_type.txt", "consumer_order.txt", @@ -85,8 +87,9 @@ public static List getTempFiles() { private File baseFolder; private File clangExecutable; private List builtinIncludes; + private File systemResourceDir; private int systemIncludesThreshold; - private ClangResources clangResources; + private final ClangResources clangResources; private final CodeParser parserConfig; @@ -98,15 +101,18 @@ public static List getTempFiles() { * @param streamConsoleOutput * @param clangExecutable * @param builtinIncludes + * @param systemResourceDir * @param parserConfig */ public ClangAstDumper(boolean streamConsoleOutput, - File clangExecutable, List builtinIncludes, CodeParser parserConfig) { + File clangExecutable, List builtinIncludes, File systemResourceDir, + CodeParser parserConfig) { this.streamConsoleOutput = streamConsoleOutput; this.clangExecutable = clangExecutable; this.builtinIncludes = builtinIncludes; + this.systemResourceDir = systemResourceDir; this.workingFolders = new ArrayList<>(); this.lastWorkingFolder = null; @@ -168,7 +174,7 @@ private ClangAstData parsePrivate(File sourceFile, String id, Standard standard, arguments.add("-Xclang"); arguments.add("-plugin-arg-DumpAst"); arguments.add("-Xclang"); - arguments.add("-system-threshold=" + systemIncludesThreshold); + arguments.add(SYSTEM_HEADER_THRESHOLD_OPTION + systemIncludesThreshold); } else { arguments.add(clangExecutable.getAbsolutePath()); @@ -176,7 +182,7 @@ private ClangAstData parsePrivate(File sourceFile, String id, Standard standard, arguments.add("-id=" + id); - arguments.add("-system-header-threshold=" + systemIncludesThreshold); + arguments.add(SYSTEM_HEADER_THRESHOLD_OPTION + systemIncludesThreshold); arguments.add("--"); } @@ -193,8 +199,10 @@ private ClangAstData parsePrivate(File sourceFile, String id, Standard standard, arguments.add("-std=cl2.0"); } // Set standard to CUDA - else if (isCuda && !standard.isCuda()) { - arguments.add("-std=cuda"); + else if (isCuda) { + // The LLVM 18 driver bundled with clang-dumper rejects '-std=cuda'. The .cu extension already + // selects CUDA mode, so use a C++ standard for host-side parsing. + arguments.add(standard.isCxx() ? standard.getFlag() : Standard.CXX17.getFlag()); } else { arguments.add(standard.getFlag()); } @@ -223,24 +231,19 @@ else if (isCuda && !standard.isCuda()) { } // If CUDA, add corresponding flags else if (isCuda) { - if (SpecsPlatforms.isWindows()) { - ClavaLog.info("CUDA parsing is not supported in Windows, run at your own risk"); - arguments.addAll(Arrays.asList("-fms-compatibility", "-D_MSC_VER", "-D_LIBCPP_MSVCRT")); + if (!SpecsPlatforms.isLinux()) { + ClavaLog.info("We only officially support CUDA parsing in Linux, run at your own risk"); + arguments.add("-fms-compatibility"); + if (SpecsPlatforms.isWindows()) { + arguments.add("-D_MSC_VER"); + arguments.add("-D_LIBCPP_MSVCRT"); + } } arguments.add("--cuda-gpu-arch=" + parserConfig.get(CodeParser.CUDA_GPU_ARCH)); var cudaPath = parserConfig.get(CodeParser.CUDA_PATH); - if (!cudaPath.isBlank()) { - - // Check if should use built-in CUDA lib - File cudaFolder = cudaPath.toUpperCase().equals(CodeParser.getBuiltinOption()) - ? clangResources.getBuiltinCudaLib() - : SpecsIo.existingFolder(cudaPath); - - ClavaLog.debug("Setting --cuda-path to folder '" + cudaFolder.getAbsolutePath() + "'"); - arguments.add("--cuda-path=" + cudaFolder.getAbsolutePath()); - } + addCudaPathArgument(arguments, cudaPath); // Since we only need parsing, enable host-only // Can help with errors such as "__float128 is not supported on this target" @@ -254,8 +257,12 @@ else if (SourceType.isHeader(sourceFile)) { arguments.add(standard.isCxx() ? "c++" : "c"); } - // If it was determined that built-in includes will be used, disable system includes - if (ClangResources.useBuiltinLibc(clangExecutable, config.get(ClangAstKeys.LIBC_CXX_MODE))) { + if (systemResourceDir != null) { + arguments.add("-resource-dir=" + systemResourceDir.getAbsolutePath()); + } + + // The parser has already resolved the libc policy before creating this per-file configuration. + if (config.get(ClangAstKeys.LIBC_CXX_MODE) == LibcMode.BUILTIN_AND_LIBC) { arguments.add("-nostdinc"); arguments.add("-nostdinc++"); } @@ -299,7 +306,7 @@ else if (SourceType.isHeader(sourceFile)) { workingFolders.add(lastWorkingFolder); output = SpecsSystem.runProcess(arguments, lastWorkingFolder, - inputStream -> this.processOutput(sourceFile, inputStream), + this::processOutput, inputStream -> this.processStdErr(inputStream, config.get(ClavaNode.CONTEXT))); if (output.isError()) { @@ -336,7 +343,24 @@ else if (SourceType.isHeader(sourceFile)) { return parsedData; } - private String processOutput(File sourceFile, InputStream inputStream) { + private void addCudaPathArgument(List arguments, String cudaPath) { + var useBuiltinCudaLib = cudaPath.toUpperCase().equals(CodeParser.getBuiltinOption()); + + if (useBuiltinCudaLib) { + File cudaFolder = clangResources.getBuiltinCudaLib(); + + ClavaLog.debug("Setting --cuda-path to built-in CUDA folder '" + + cudaFolder.getAbsolutePath() + "'"); + arguments.add("--cuda-path=" + cudaFolder.getAbsolutePath()); + } else if (!cudaPath.isBlank()) { + File cudaFolder = SpecsIo.existingFolder(cudaPath); + + ClavaLog.debug("Setting --cuda-path to folder '" + cudaFolder.getAbsolutePath() + "'"); + arguments.add("--cuda-path=" + cudaFolder.getAbsolutePath()); + } + } + + private String processOutput(InputStream inputStream) { StringBuilder output = new StringBuilder(); try (LineStream lines = LineStream.newInstance(inputStream, null)) { diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstParser.java b/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstParser.java index 23d6051050..ccfb24385e 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstParser.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/dumper/ClangAstParser.java @@ -147,7 +147,6 @@ public TranslationUnit parseTu(File sourceFile) { } ClavaNode parsedNode = data.get(ClangAstData.CLAVA_NODES).get(topLevelTypeId); Objects.requireNonNull(parsedNode, () -> "No node for type '" + topLevelTypeId + "'"); - } // Parse top-level attributes diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodeParser.java b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodeParser.java index 0cfe3473f8..19d3bfbcfb 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodeParser.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodeParser.java @@ -171,10 +171,6 @@ private ClavaNode parseNode(String nodeId, String classname, ClangAstData data, if (nodeData == null) { throw new RuntimeException("No ClavaData/DataStore for node '" + nodeId + "' (classname: " + classname + "), data dumper is not being called (linestream index '" + lineStream.getLastLineIndex() + "')"); - // if (debug) - // SpecsLogs.msgInfo("No ClavaData for node '" + nodeId + "' (classname: " + classname - // + "), data dumper is not being called"); - // return new UnsupportedNode(classname, ClavaData.empty(), Collections.emptyList()); } // Get corresponding ClavaNode class @@ -240,8 +236,7 @@ private ClavaNode parseNode(String nodeId, String classname, ClangAstData data, int index = i; Objects.requireNonNull(child, () -> "Did not find ClavaNode for child with index '" + index + "' and id '" + childId - + "' when parsing " - + clavaNodeClass.getSimpleName() + " -> " + nodeData); + + "' when parsing " + clavaNodeClass.getSimpleName() + " -> " + nodeData); child = processChild(child, clavaNodeClass, data); diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodes.java b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodes.java index 964fe3889a..30438176cc 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodes.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/ClavaNodes.java @@ -148,9 +148,9 @@ public void queueSetNode(DataClass data, DataKey key + "', if node can be null, use queueOptional instead. Node data:\n" + data); } - // Get node - ClavaNode node = get(nodeId); - + ClavaNode node = Objects.requireNonNull(clavaNodes.get(nodeId), + () -> "Could not resolve required node '" + nodeId + "' for key '" + key.getName() + + "'. Node data:\n" + data); Class valueClass = key.getValueClass(); ClavaNode adaptedNode = adaptNode(node, valueClass); @@ -199,8 +199,11 @@ public void queueSetOptionalNode(DataClass data, DataKe Runnable nodeToAdd = () -> { + @SuppressWarnings("unchecked") Optional value = isNullId(nodeId) ? Optional.empty() - : key.getValueClass().cast(getOptional(nodeId)); + : Optional.of((T) Objects.requireNonNull(clavaNodes.get(nodeId), + () -> "Could not resolve optional node '" + nodeId + "' for key '" + key.getName() + + "'. Node data:\n" + data)); data.set(key, value); }; @@ -213,7 +216,10 @@ public void queueSetNullableNode(DataClass data, DataKe Runnable nodeToAdd = () -> { - ClavaNode value = isNullId(nodeId) ? getNullNodeType(nodeId).newNullNode(factory) : get(nodeId); + ClavaNode value = isNullId(nodeId) ? getNullNodeType(nodeId).newNullNode(factory) + : Objects.requireNonNull(clavaNodes.get(nodeId), + () -> "Could not resolve nullable node '" + nodeId + "' for key '" + key.getName() + + "'. Node data:\n" + data); data.set(key, key.getValueClass().cast(value)); }; @@ -227,7 +233,11 @@ public void queueSetNodeList(DataClass data, DataKey
  • { @SuppressWarnings("unchecked") // If the nodes exist, they should be of the requested type - List nodes = nodeIds.stream().map(id -> (T) get(id)).collect(Collectors.toList()); + List nodes = nodeIds.stream() + .map(id -> (T) Objects.requireNonNull(clavaNodes.get(id), + () -> "Could not resolve node '" + id + "' in list for key '" + key.getName() + + "'. Node data:\n" + data)) + .collect(Collectors.toList()); data.set(key, nodes); }; diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/LanguageParser.java b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/LanguageParser.java index e366767bce..3524f18bad 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/LanguageParser.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/LanguageParser.java @@ -55,6 +55,7 @@ public void apply(LineStream lineStream, ClangAstData data) { .set(Language.C_PLUS_PLUS_17, LineStreamParsers.oneOrZero(lineStream)) .set(Language.C_PLUS_PLUS_20, LineStreamParsers.oneOrZero(lineStream)) .set(Language.C_PLUS_PLUS_23, LineStreamParsers.oneOrZero(lineStream)) + .set(Language.C_PLUS_PLUS_26, LineStreamParsers.oneOrZero(lineStream)) .set(Language.HAS_DIGRAPHS, LineStreamParsers.oneOrZero(lineStream)) .set(Language.IS_GNU, LineStreamParsers.oneOrZero(lineStream)) .set(Language.HEX_FLOATS, LineStreamParsers.oneOrZero(lineStream)) diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/ExprDataParser.java b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/ExprDataParser.java index 3687d9e622..8582135167 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/ExprDataParser.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/ExprDataParser.java @@ -119,7 +119,7 @@ public static DataStore parseCharacterLiteralData(LineStream lines, ClangAstData DataStore data = parseLiteralData(lines, dataStore); data.add(CharacterLiteral.VALUE, LineStreamParsers.longInt(lines)); - data.add(CharacterLiteral.KIND, LineStreamParsers.enumFromInt(CharacterKind.getEnumHelper(), lines)); + data.add(CharacterLiteral.KIND, LineStreamParsers.enumFromName(CharacterKind.getEnumHelper(), lines)); return data; } diff --git a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/TypeDataParser.java b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/TypeDataParser.java index 2dbe71624f..48d743ff2b 100644 --- a/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/TypeDataParser.java +++ b/ClangAstParser/src/pt/up/fe/specs/clang/parsers/data/TypeDataParser.java @@ -366,7 +366,7 @@ public static DataStore parseUnaryTransformTypeData(LineStream lines, ClangAstDa DataStore data = parseTypeData(lines, parserData); data.add(UnaryTransformType.KIND, LineStreamParsers.enumFromName(UnaryTransformTypeKind.class, lines)); - parserData.getClavaNodes().queueSetNode(data, UnaryTransformType.UNDERLYING_TYPE, lines.nextLine()); + parserData.getClavaNodes().queueSetOptionalNode(data, UnaryTransformType.UNDERLYING_TYPE, lines.nextLine()); parserData.getClavaNodes().queueSetNode(data, UnaryTransformType.BASE_TYPE, lines.nextLine()); return data; diff --git a/ClangAstParser/test-resources/cxx/dependent_scope_decl_ref_expr.cpp.txt b/ClangAstParser/test-resources/cxx/dependent_scope_decl_ref_expr.cpp.txt index cce55922e1..5b84d42dc7 100644 --- a/ClangAstParser/test-resources/cxx/dependent_scope_decl_ref_expr.cpp.txt +++ b/ClangAstParser/test-resources/cxx/dependent_scope_decl_ref_expr.cpp.txt @@ -7,5 +7,6 @@ void compute_boundaries(FloatType value) { // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) // If v is normalized: // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) - static_assert(std::numeric_limits::is_iec559, "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + static_assert(std::numeric_limits::is_iec559, "internal error: dtoa_short requires an IEEE-754 " + "floating-point implementation"); } diff --git a/ClangAstParser/test-resources/cxx/paren_list_initialization.cpp b/ClangAstParser/test-resources/cxx/paren_list_initialization.cpp new file mode 100644 index 0000000000..8b84bb9cfb --- /dev/null +++ b/ClangAstParser/test-resources/cxx/paren_list_initialization.cpp @@ -0,0 +1,8 @@ +struct Point { + int x; + int y; +}; + +void test() { + Point point(1, 2); +} diff --git a/ClangAstParser/test-resources/cxx/source_locations.cpp b/ClangAstParser/test-resources/cxx/source_locations.cpp new file mode 100644 index 0000000000..a80c933e55 --- /dev/null +++ b/ClangAstParser/test-resources/cxx/source_locations.cpp @@ -0,0 +1,17 @@ +#define VALUE 7 +#define CAT_IMPL(left, right) left##right +#define CAT(left, right) CAT_IMPL(left, right) +#define DECL(name) int name = VALUE; + +DECL(CAT(macro_, value)) +int ordinary = 0; +int foobar = 1; +int pasted_reference = CAT(foo, bar); + +namespace std { +using uint8_t = unsigned char; +template class vector; +} // namespace std + +template > +class Holder {}; diff --git a/ClangAstParser/test-resources/cxx/unevaluated_strings.cpp b/ClangAstParser/test-resources/cxx/unevaluated_strings.cpp new file mode 100644 index 0000000000..b808d729be --- /dev/null +++ b/ClangAstParser/test-resources/cxx/unevaluated_strings.cpp @@ -0,0 +1,3 @@ +static_assert(true, "plain message"); +static_assert(true, "line\nbreak"); +static_assert(true, "\u00e9"); diff --git a/ClangAstParser/test-resources/cxx/unevaluated_strings.cpp.txt b/ClangAstParser/test-resources/cxx/unevaluated_strings.cpp.txt new file mode 100644 index 0000000000..b808d729be --- /dev/null +++ b/ClangAstParser/test-resources/cxx/unevaluated_strings.cpp.txt @@ -0,0 +1,3 @@ +static_assert(true, "plain message"); +static_assert(true, "line\nbreak"); +static_assert(true, "\u00e9"); diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/ClangResourcesTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/ClangResourcesTest.java new file mode 100644 index 0000000000..3169d7b778 --- /dev/null +++ b/ClangAstParser/test/pt/up/fe/specs/clang/ClangResourcesTest.java @@ -0,0 +1,794 @@ +/** + * Copyright 2026 SPeCS. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import pt.up.fe.specs.clang.ClangAstWebResource.ClangDumperManifest; +import pt.up.fe.specs.clang.ClangAstWebResource.ClangDumperManifestAsset; +import pt.up.fe.specs.clang.ClangAstWebResource.LocalBuild; +import pt.up.fe.specs.clang.ClangAstWebResource.Release; +import pt.up.fe.specs.clang.codeparser.CodeParser; +import pt.up.fe.specs.clang.dumper.ClangAstDumper; +import pt.up.fe.specs.clang.parsers.TopLevelNodesParser; +import pt.up.fe.specs.util.providers.FileResourceProvider; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.FileTime; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.HexFormat; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class ClangResourcesTest { + + private static final Duration PROCESS_TIMEOUT = Duration.ofSeconds(30); + private static final String HELLO_SHA256 = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"; + + @TempDir + Path tempFolder; + + @Test + public void releaseTagIsParsedAsRelease() { + var release = assertInstanceOf(Release.class, ClangAstWebResource.parseDumperSource("v16.0.5_3")); + + assertEquals("v16.0.5_3", release.tag()); + } + + @Test + public void absolutePathIsParsedAsLocalBuild() { + var localBuild = assertInstanceOf(LocalBuild.class, + ClangAstWebResource.parseDumperSource(tempFolder.toString())); + + assertEquals(tempFolder.toFile(), localBuild.folder()); + } + + @Test + public void relativePathIsRejected() { + assertThrows(RuntimeException.class, + () -> ClangAstWebResource.parseDumperSource("../clang-dumper/build")); + } + + @Test + public void localBuildSelectsExpectedTool() throws IOException { + var toolName = ClangAstDumper.usePlugin() + ? System.mapLibraryName("plugin") + : SupportedPlatform.getCurrentPlatform().isWindows() ? "tool.exe" : "tool"; + var tool = tempFolder.resolve(toolName).toFile(); + assertTrue(tool.createNewFile()); + + assertEquals(tool, ClangResources.getLocalExecutable(tempFolder.toFile())); + } + + @Test + public void localBuildRequiresExpectedTool() { + assertThrows(RuntimeException.class, () -> ClangResources.getLocalExecutable(tempFolder.toFile())); + } + + @Test + public void manifestValidationAndAssetSelectionArePreserved() { + var tool = asset("tool", "tool", "linux", "x64"); + var plugin = asset("plugin", "plugin", "linux", "x64"); + var manifest = new ClangDumperManifest(1, List.of(tool, plugin)); + + assertDoesNotThrow(manifest::validate); + assertEquals(tool, manifest.getAsset("linux", "x64", "tool")); + assertEquals(plugin, manifest.getAsset("linux", "x64", "plugin")); + assertEquals(HELLO_SHA256, tool.sha256()); + assertThrows(RuntimeException.class, () -> manifest.getAsset("windows", "x64", "tool")); + assertThrows(RuntimeException.class, () -> new ClangDumperManifest(2, List.of(tool)).validate()); + assertThrows(RuntimeException.class, () -> new ClangDumperManifest(1, List.of()).validate()); + } + + @Test + public void includesCacheValidationChecksEntrypointsButNotEveryFile() throws IOException { + var includesFolder = tempFolder.resolve("includes"); + assertFalse(ClangResources.isIncludesCacheValid(includesFolder.toFile())); + + Files.createDirectories(includesFolder.resolve("builtin")); + Files.writeString(includesFolder.resolve("entrypoints.txt"), "builtin\n"); + Files.writeString(includesFolder.resolve("builtin/header.h"), "original"); + Files.writeString(includesFolder.resolve("unexpected.txt"), "extra"); + + assertTrue(ClangResources.isIncludesCacheValid(includesFolder.toFile())); + + Files.writeString(includesFolder.resolve("builtin/header.h"), "modified"); + assertTrue(ClangResources.isIncludesCacheValid(includesFolder.toFile())); + Files.writeString(includesFolder.resolve("entrypoints.txt"), "missing\n"); + assertFalse(ClangResources.isIncludesCacheValid(includesFolder.toFile())); + } + + @Test + public void entrypointsPreserveDeclaredIncludeOrder() throws IOException { + var includesFolder = Files.createDirectories(tempFolder.resolve("includes")); + var first = Files.createDirectories(includesFolder.resolve("first")); + var second = Files.createDirectories(includesFolder.resolve("second")); + Files.writeString(includesFolder.resolve("entrypoints.txt"), "second\nfirst\n"); + + assertEquals(List.of(second.toFile(), first.toFile()), + ClangResources.getIncludeFolders(includesFolder.toFile())); + } + + @Test + public void releasesWithTheSameIncludesShaShareOneExtraction() throws Exception { + var archive = createIncludesArchive(); + var sha = sha256(archive); + var firstAsset = new ClangDumperManifestAsset("v1-includes.zip", "includes", "linux", "x64", 18, sha); + var secondAsset = new ClangDumperManifestAsset("v2-includes.zip", "includes", "linux", "x64", 18, sha); + var firstManifest = new ClangDumperManifest(1, List.of(firstAsset)); + var secondManifest = new ClangDumperManifest(1, List.of(secondAsset)); + var firstRelease = Files.createDirectories(tempFolder.resolve("releases/v1")); + var secondRelease = Files.createDirectories(tempFolder.resolve("releases/v2")); + var firstWrites = new AtomicInteger(); + var secondWrites = new AtomicInteger(); + + firstManifest.validate(); + secondManifest.validate(); + assertNotEquals(firstRelease, secondRelease); + + var firstIncludes = ClangResources.resolveIncludes(tempFolder.toFile(), firstAsset, + copyingResource(archive, firstWrites)); + var secondIncludes = ClangResources.resolveIncludes(tempFolder.toFile(), secondAsset, + copyingResource(archive, secondWrites)); + + assertEquals(firstAsset, firstManifest.getAsset("linux", "x64", "includes")); + assertEquals(secondAsset, secondManifest.getAsset("linux", "x64", "includes")); + assertEquals(firstIncludes, secondIncludes); + assertEquals(1, firstWrites.get()); + assertEquals(0, secondWrites.get()); + assertTrue(ClangResources.isIncludesCacheValid(firstIncludes)); + try (var children = Files.list(tempFolder.resolve("includes"))) { + assertEquals(1, children.filter(Files::isDirectory).count()); + } + } + + @Test + public void invalidPublishedIncludesFailWithoutRepair() throws IOException { + var sha = "a".repeat(64); + var invalidFolder = ClangResources.getSharedIncludesFolder(tempFolder.toFile(), sha); + Files.createDirectories(invalidFolder.toPath()); + Files.writeString(invalidFolder.toPath().resolve("entrypoints.txt"), "missing\n"); + var writes = new AtomicInteger(); + var unusedArchive = tempFolder.resolve("unused.zip"); + + var error = assertThrows(RuntimeException.class, + () -> ClangResources.resolveIncludes(tempFolder.toFile(), + new ClangDumperManifestAsset("includes.zip", "includes", "linux", "x64", 18, sha), + copyingResource(unusedArchive, writes))); + + assertTrue(error.getMessage().contains(invalidFolder.getAbsolutePath())); + assertTrue(error.getMessage().contains(sha)); + assertTrue(error.getMessage().contains("delete this directory manually to regenerate")); + assertTrue(invalidFolder.isDirectory()); + assertEquals("missing\n", Files.readString(invalidFolder.toPath().resolve("entrypoints.txt"))); + assertEquals(0, writes.get()); + } + + @Test + public void corruptNewDownloadIsRejectedWithoutRetry() throws IOException { + var source = Files.writeString(tempFolder.resolve("source"), "bad"); + var writes = new AtomicInteger(); + var destination = tempFolder.resolve("release/tool").toFile(); + + assertThrows(RuntimeException.class, + () -> CacheFiles.installFile(tempFolder, destination, copyingResource(source, writes), HELLO_SHA256, + "test asset")); + + assertEquals(1, writes.get()); + assertFalse(destination.exists()); + try (var children = Files.list(destination.getParentFile().toPath())) { + assertTrue(children.noneMatch(path -> path.getFileName().toString().startsWith(".tool.tmp-"))); + } + } + + @Test + public void existingReleaseResourceIsReused() throws IOException { + var destination = tempFolder.resolve("release/tool").toFile(); + Files.createDirectories(destination.toPath().getParent()); + Files.writeString(destination.toPath(), "cached"); + var writes = new AtomicInteger(); + var source = Files.writeString(tempFolder.resolve("source"), "new"); + + assertEquals(destination, + CacheFiles.installFile(tempFolder, destination, copyingResource(source, writes), HELLO_SHA256, + "test asset")); + assertEquals(0, writes.get()); + assertEquals("cached", Files.readString(destination.toPath())); + } + + @Test + public void concurrentInitializationLeavesOneValidIncludesTree() throws Exception { + var archive = createIncludesArchive(); + var sha = sha256(archive); + var asset = new ClangDumperManifestAsset("includes.zip", "includes", "linux", "x64", 18, sha); + var writes = new AtomicInteger(); + var executor = Executors.newFixedThreadPool(4); + var futures = new ArrayList>(); + + try { + for (int i = 0; i < 4; i++) { + futures.add(executor.submit(() -> ClangResources.resolveIncludes(tempFolder.toFile(), asset, + copyingResource(archive, writes)).toPath())); + } + + for (var future : futures) { + assertEquals(ClangResources.getSharedIncludesFolder(tempFolder.toFile(), sha).toPath(), + future.get(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)); + } + } finally { + executor.shutdownNow(); + executor.awaitTermination(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } + + var finalFolder = ClangResources.getSharedIncludesFolder(tempFolder.toFile(), sha); + assertTrue(ClangResources.isIncludesCacheValid(finalFolder)); + assertTrue(writes.get() >= 1); + try (var children = Files.list(finalFolder.toPath().getParent())) { + var childPaths = children.toList(); + assertEquals(1, childPaths.stream().filter(Files::isDirectory).count()); + assertTrue(childPaths.stream() + .noneMatch(path -> path.getFileName().toString().startsWith("." + sha + ".tmp-"))); + } + } + + @Test + public void activelyLockedStagingDirectoriesArePreserved() throws Exception { + var includesRoot = Files.createDirectories(tempFolder.resolve("includes")); + var staging = CacheFiles.createStagingDirectory(tempFolder, includesRoot, ".sha.tmp-"); + try { + CacheFiles.deleteUnlockedStagingLocks(tempFolder, includesRoot); + assertTrue(Files.exists(staging.path())); + assertTrue(Files.exists(staging.lockPath())); + } finally { + staging.close(); + CacheFiles.delete(staging.path()); + } + } + + @Test + public void unlockedStagingDirectoriesAreCleaned() throws Exception { + var includesRoot = Files.createDirectories(tempFolder.resolve("includes")); + var staging = CacheFiles.createStagingDirectory(tempFolder, includesRoot, ".sha.tmp-"); + var stagingPath = staging.path(); + var lockPath = staging.lockPath(); + staging.close(); + Files.createFile(lockPath); + + assertTrue(Files.exists(lockPath)); + CacheFiles.deleteUnlockedStagingLocks(tempFolder, includesRoot); + + assertFalse(Files.exists(stagingPath)); + assertFalse(Files.exists(lockPath)); + } + + @Test + public void orphanedStagingLocksAreCleaned() throws IOException { + var includesRoot = Files.createDirectories(tempFolder.resolve("includes")); + var lockPath = includesRoot.resolve(".orphan.tmp-123.lock"); + Files.createFile(lockPath); + + CacheFiles.deleteUnlockedStagingLocks(tempFolder, includesRoot); + + assertFalse(Files.exists(lockPath)); + } + + @Test + public void staleReleaseAndSharedIncludesAreRemovedAfterSixtyDays() throws IOException { + var clangCacheRoot = clangCacheRoot(); + var releases = Files.createDirectories(clangCacheRoot.resolve("releases")); + var current = Files.createDirectories(releases.resolve("current")); + var staleRelease = Files.createDirectories(releases.resolve("stale")); + var staleIncludes = Files.createDirectories( + ClangResources.getSharedIncludesFolder(clangCacheRoot.toFile(), "c".repeat(64)).toPath() + .resolve("builtin")); + Files.writeString(staleIncludes.getParent().resolve("entrypoints.txt"), "builtin\n"); + var old = FileTime.from(Instant.now().minus(Duration.ofDays(61))); + Files.setLastModifiedTime(staleRelease, old); + Files.setLastModifiedTime(staleIncludes.getParent(), old); + + var parser = CodeParser.newInstance(); + parser.set(CodeParser.DUMPER_FOLDER, tempFolder.toFile()); + new ClangResources(parser).deleteStaleVersions(Instant.now(), current.toFile()); + + assertTrue(Files.exists(current)); + assertFalse(Files.exists(staleRelease)); + assertFalse(Files.exists(staleIncludes.getParent())); + } + + @Test + public void usingSharedIncludesRefreshesItsLastUsedTime() throws IOException { + var sha = "d".repeat(64); + var clangCacheRoot = clangCacheRoot(); + var shared = Files.createDirectories( + ClangResources.getSharedIncludesFolder(clangCacheRoot.toFile(), sha).toPath()); + Files.createDirectories(shared.resolve("builtin")); + Files.writeString(shared.resolve("entrypoints.txt"), "builtin\n"); + Files.setLastModifiedTime(shared, FileTime.from(Instant.now().minus(Duration.ofDays(61)))); + var writes = new AtomicInteger(); + var unusedArchive = tempFolder.resolve("unused.zip"); + var asset = new ClangDumperManifestAsset("includes.zip", "includes", "linux", "x64", 18, sha); + assertEquals(shared.toFile(), ClangResources.resolveIncludes(clangCacheRoot.toFile(), asset, + copyingResource(unusedArchive, writes))); + assertEquals(0, writes.get()); + + var parser = CodeParser.newInstance(); + parser.set(CodeParser.DUMPER_FOLDER, tempFolder.toFile()); + new ClangResources(parser).deleteStaleVersions(Instant.now(), + Files.createDirectories(clangCacheRoot.resolve("releases/current")).toFile()); + + assertTrue(Files.exists(shared)); + } + + @Test + public void maintenanceLockMakesUsageWinOverContendingCleanup() throws Exception { + var releases = Files.createDirectories(tempFolder.resolve("releases")); + var stale = Files.createDirectories(releases.resolve("stale")); + Files.setLastModifiedTime(stale, FileTime.from(Instant.now().minus(Duration.ofDays(61)))); + var usageStarted = new CountDownLatch(1); + var allowUsageToFinish = new CountDownLatch(1); + var cleanupStarted = new CountDownLatch(1); + var executor = Executors.newFixedThreadPool(2); + + try { + var usage = executor.submit(() -> CacheFiles.withMaintenanceLock(tempFolder, () -> { + CacheFiles.touch(stale); + usageStarted.countDown(); + awaitLatch(allowUsageToFinish); + })); + assertTrue(usageStarted.await(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)); + + var cleanup = executor.submit(() -> { + cleanupStarted.countDown(); + CacheFiles.deleteStaleDirectories(tempFolder, releases, + Instant.now().minus(Duration.ofDays(60)), null); + }); + assertTrue(cleanupStarted.await(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)); + assertFalse(cleanup.isDone()); + + allowUsageToFinish.countDown(); + usage.get(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + cleanup.get(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + assertTrue(Files.exists(stale)); + } finally { + allowUsageToFinish.countDown(); + executor.shutdownNow(); + executor.awaitTermination(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } + } + + @Test + public void cleanupWinnerMakesSubsequentIncludesResolutionAcknowledgeTheMiss() throws Exception { + var archive = createIncludesArchive(); + var sha = sha256(archive); + var asset = new ClangDumperManifestAsset("includes.zip", "includes", "linux", "x64", 18, sha); + var shared = ClangResources.getSharedIncludesFolder(tempFolder.toFile(), sha); + Files.createDirectories(shared.toPath().resolve("builtin")); + Files.writeString(shared.toPath().resolve("entrypoints.txt"), "builtin\n"); + Files.setLastModifiedTime(shared.toPath(), FileTime.from(Instant.now().minus(Duration.ofDays(61)))); + + CacheFiles.deleteStaleDirectories(tempFolder, shared.toPath().getParent(), + Instant.now().minus(Duration.ofDays(60)), null); + assertFalse(shared.exists()); + + var writes = new AtomicInteger(); + assertEquals(shared, ClangResources.resolveIncludes(tempFolder.toFile(), asset, + copyingResource(archive, writes))); + assertEquals(1, writes.get()); + } + + @Test + public void releaseResourcesCanBeInitializedBySeparateJvms() throws Exception { + var cacheFolder = Files.createDirectory(tempFolder.resolve("cache")).toFile(); + var firstDone = tempFolder.resolve("first.done"); + var secondDone = tempFolder.resolve("second.done"); + var firstLog = tempFolder.resolve("first.log"); + var secondLog = tempFolder.resolve("second.log"); + + Process first = startResourceProcess(cacheFolder, firstDone, firstLog); + Process second = startResourceProcess(cacheFolder, secondDone, secondLog); + try { + waitForProcess(first, firstLog); + waitForProcess(second, secondLog); + } finally { + stopProcess(first); + stopProcess(second); + } + + var firstExecutable = new File(Files.readString(firstDone).trim()); + var secondExecutable = new File(Files.readString(secondDone).trim()); + assertEquals(firstExecutable.getAbsoluteFile(), secondExecutable.getAbsoluteFile()); + assertTrue(firstExecutable.isFile()); + assertTrue(cacheFolder.toPath().resolve("clang-dumper").resolve("releases") + .resolve(ClangAstWebResource.getReleaseTag()).toFile().isDirectory()); + } + + @Test + public void maintenanceLockIsSharedAcrossJvmProcesses() throws Exception { + var holder = startMaintenanceProcess(MaintenanceLockHolderProcess.class, tempFolder); + var contender = (Process) null; + try (var holderOutput = new BufferedReader( + new InputStreamReader(holder.getInputStream(), StandardCharsets.UTF_8))) { + assertEquals("READY", holderOutput.readLine()); + + contender = startMaintenanceProcess(MaintenanceLockProbeProcess.class, tempFolder); + try (var contenderOutput = new BufferedReader( + new InputStreamReader(contender.getInputStream(), StandardCharsets.UTF_8))) { + assertEquals("BLOCKED", contenderOutput.readLine()); + + holder.getOutputStream().write('\n'); + holder.getOutputStream().flush(); + assertEquals("DONE", holderOutput.readLine()); + + contender.getOutputStream().write('\n'); + contender.getOutputStream().flush(); + assertEquals("ENTERED", contenderOutput.readLine()); + assertEquals("DONE", contenderOutput.readLine()); + assertTrue(contender.waitFor(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)); + assertEquals(0, contender.exitValue()); + } + } finally { + try { + holder.getOutputStream().write('\n'); + holder.getOutputStream().flush(); + } catch (IOException ignored) { + // The holder may already have exited after the assertion path. + } + if (contender != null) { + try { + contender.getOutputStream().write('\n'); + contender.getOutputStream().flush(); + } catch (IOException ignored) { + // The contender may already have exited after the assertion path. + } + } + stopProcess(contender); + stopProcess(holder); + } + } + + @Test + public void sameJvmInstancesReuseReleaseFilesAndPrepareIncludesOnlyForBuiltinLibc() throws Exception { + var firstParser = newParser(""); + var secondParser = newParser(""); + var thirdParser = newParser(""); + var firstResources = new ClangResources(firstParser); + var secondResources = new ClangResources(secondParser); + var thirdResources = new ClangResources(thirdParser); + + var executor = Executors.newFixedThreadPool(3); + try { + var first = executor.submit(() -> firstResources.getClangFiles(LibcMode.SYSTEM)); + var second = executor.submit(() -> secondResources.getClangFiles(LibcMode.SYSTEM)); + var third = executor.submit(() -> thirdResources.getClangFiles(LibcMode.BUILTIN_AND_LIBC)); + + var firstFiles = first.get(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + var secondFiles = second.get(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + var thirdFiles = third.get(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + + assertEquals(firstFiles, secondFiles); + assertEquals(firstFiles.clangExecutable().getAbsoluteFile(), thirdFiles.clangExecutable().getAbsoluteFile()); + assertTrue(firstFiles.clangExecutable().isFile()); + assertTrue(firstFiles.builtinIncludes().isEmpty()); + assertTrue(secondFiles.builtinIncludes().isEmpty()); + assertFalse(thirdFiles.builtinIncludes().isEmpty()); + + var shared = new File(thirdFiles.builtinIncludes().get(0)).toPath(); + while (!Files.isRegularFile(shared.resolve("entrypoints.txt"))) { + shared = shared.getParent(); + } + Files.setLastModifiedTime(shared, FileTime.from(Instant.now().minus(Duration.ofDays(61)))); + thirdResources.getClangFiles(LibcMode.BUILTIN_AND_LIBC); + assertTrue(Files.getLastModifiedTime(shared).toInstant().isAfter(Instant.now().minus(Duration.ofDays(1)))); + } finally { + executor.shutdownNow(); + executor.awaitTermination(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } + } + + @Test + public void builtinCudaAutoSystemLibcUsesSameResourcePathAsExplicitSystem() { + var parser = newParser(CodeParser.getBuiltinOption()); + var resources = new ClangResources(parser); + var autoFiles = resources.getClangFiles(LibcMode.AUTO); + var systemFiles = resources.getClangFiles(LibcMode.SYSTEM); + + assertEquals(LibcMode.SYSTEM, autoFiles.libcMode()); + assertEquals(LibcMode.SYSTEM, systemFiles.libcMode()); + assertTrue(autoFiles.builtinIncludes().isEmpty()); + assertEquals(systemFiles.systemResourceDir(), autoFiles.systemResourceDir()); + assertNotNull(autoFiles.systemResourceDir()); + assertTrue(autoFiles.systemResourceDir().isDirectory()); + assertFalse(Files.exists(clangCacheRoot().resolve("includes"))); + } + + @Test + public void builtinCudaArchiveHasCanonicalInstallationLayout() { + var parser = newParser(CodeParser.getBuiltinOption()); + var cudaFolder = new ClangResources(parser).getBuiltinCudaLib(); + + var cudaPlatform = cudaFolder.getParentFile().getName(); + assertEquals(tempFolder.resolve("cuda").resolve(ClangAstWebResource.getCudaReleaseTag()) + .resolve(cudaPlatform).resolve("cudalib").toFile().getAbsolutePath(), cudaFolder.getAbsolutePath()); + assertTrue(new File(cudaFolder, "include/cuda.h").isFile()); + assertTrue(new File(cudaFolder, "include/cuda_runtime.h").isFile()); + assertTrue(new File(cudaFolder, "nvvm/libdevice/libdevice.10.bc").isFile()); + } + + @Test + public void libcDetectionIsScopedToTheExecutable() throws IOException { + assumeTrue(!SupportedPlatform.getCurrentPlatform().isWindows(), "Shell fixtures require a Unix executable"); + + var systemLibcDumper = tempFolder.resolve("system-libc-dumper"); + Files.writeString(systemLibcDumper, + "#!/bin/sh\nprintf '%s\\n' '" + TopLevelNodesParser.getTopLevelNodesHeader() + "'\n"); + assertTrue(systemLibcDumper.toFile().setExecutable(true)); + + var builtinLibcDumper = tempFolder.resolve("builtin-libc-dumper"); + Files.writeString(builtinLibcDumper, "#!/bin/sh\nexit 1\n"); + assertTrue(builtinLibcDumper.toFile().setExecutable(true)); + + assertEquals(LibcMode.SYSTEM, + ClangResources.resolveLibcMode(systemLibcDumper.toFile(), LibcMode.AUTO, false)); + assertEquals(LibcMode.BUILTIN_AND_LIBC, + ClangResources.resolveLibcMode(builtinLibcDumper.toFile(), LibcMode.AUTO, false)); + assertEquals(LibcMode.SYSTEM, + ClangResources.resolveLibcMode(systemLibcDumper.toFile(), LibcMode.SYSTEM, false)); + assertEquals(LibcMode.BUILTIN_AND_LIBC, + ClangResources.resolveLibcMode(builtinLibcDumper.toFile(), LibcMode.BUILTIN_AND_LIBC, false)); + } + + @Test + public void forcedBuildAndPluginModesResolveToSystemWithoutAutoState() throws IOException { + assumeTrue(!SupportedPlatform.getCurrentPlatform().isWindows(), "Shell fixtures require a Unix executable"); + + var dumper = tempFolder.resolve("dumper"); + Files.writeString(dumper, "#!/bin/sh\nexit 1\n"); + assertTrue(dumper.toFile().setExecutable(true)); + + assertEquals(LibcMode.SYSTEM, + ClangResources.resolveLibcMode(dumper.toFile(), LibcMode.BUILTIN_AND_LIBC, true)); + assertEquals(LibcMode.SYSTEM, + ClangResources.resolveLibcMode(dumper.toFile(), LibcMode.AUTO, true)); + assertThrows(IllegalArgumentException.class, + () -> new ClangFiles(dumper.toFile(), List.of(), null, LibcMode.AUTO)); + } + + private CodeParser newParser(String cudaPath) { + var parser = CodeParser.newInstance(); + parser.set(CodeParser.DUMPER_FOLDER, tempFolder.toFile()); + parser.set(CodeParser.CUDA_PATH, cudaPath); + return parser; + } + + private Path clangCacheRoot() { + return tempFolder.resolve("clang-dumper"); + } + + private static ClangDumperManifestAsset asset(String filename, String kind, String platform, String arch) { + return new ClangDumperManifestAsset(filename, kind, platform, arch, 18, HELLO_SHA256); + } + + private static FileResourceProvider copyingResource(Path source, AtomicInteger writes) { + return new FileResourceProvider() { + @Override + public File write(File folder) { + writes.incrementAndGet(); + try { + var destination = folder.toPath().resolve(getFilename()); + Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING); + return destination.toFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public String version() { + return "test"; + } + + @Override + public String getFilename() { + return source.getFileName().toString(); + } + }; + } + + private static void awaitLatch(CountDownLatch latch) { + try { + if (!latch.await(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)) { + throw new RuntimeException("Timed out waiting for maintenance-lock test coordination"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } + + private Path createIncludesArchive() throws IOException { + var archive = tempFolder.resolve("includes.zip"); + try (var zip = new ZipOutputStream(Files.newOutputStream(archive))) { + zip.putNextEntry(new ZipEntry("builtin/")); + zip.closeEntry(); + zip.putNextEntry(new ZipEntry("entrypoints.txt")); + zip.write("builtin\n".getBytes(StandardCharsets.UTF_8)); + zip.closeEntry(); + zip.putNextEntry(new ZipEntry("builtin/header.h")); + zip.write("header\n".getBytes(StandardCharsets.UTF_8)); + zip.closeEntry(); + } + + return archive; + } + + private static String sha256(Path file) throws IOException { + try { + return HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256") + .digest(Files.readAllBytes(file))); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + private Process startResourceProcess(File cacheFolder, Path done, Path log) throws IOException { + var javaExecutable = Path.of(System.getProperty("java.home"), "bin", + SupportedPlatform.getCurrentPlatform().isWindows() ? "java.exe" : "java"); + + return new ProcessBuilder( + javaExecutable.toString(), + "-cp", + System.getProperty("java.class.path"), + ResourceProcess.class.getName(), + cacheFolder.getAbsolutePath(), + done.toAbsolutePath().toString()) + .redirectErrorStream(true) + .redirectOutput(log.toFile()) + .start(); + } + + private Process startMaintenanceProcess(Class processClass, Path cacheFolder) throws IOException { + var javaExecutable = Path.of(System.getProperty("java.home"), "bin", + SupportedPlatform.getCurrentPlatform().isWindows() ? "java.exe" : "java"); + + return new ProcessBuilder( + javaExecutable.toString(), + "-cp", + System.getProperty("java.class.path"), + processClass.getName(), + cacheFolder.toAbsolutePath().toString()) + .start(); + } + + private void waitForProcess(Process process, Path log) throws Exception { + assertTrue(process.waitFor(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS), + () -> "Child JVM did not finish. Output: " + readLog(log)); + assertEquals(0, process.exitValue(), () -> "Child JVM failed. Output: " + readLog(log)); + } + + private String readLog(Path log) { + try { + return Files.readString(log); + } catch (IOException e) { + return ""; + } + } + + private void stopProcess(Process process) throws InterruptedException { + if (process == null || !process.isAlive()) { + return; + } + + process.destroyForcibly(); + process.waitFor(PROCESS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } + + public static final class ResourceProcess { + + private ResourceProcess() { + } + + public static void main(String[] args) throws Exception { + var parser = CodeParser.newInstance(); + parser.set(CodeParser.DUMPER_FOLDER, new File(args[0])); + var clangFiles = new ClangResources(parser).getClangFiles(LibcMode.SYSTEM); + Files.writeString(Path.of(args[1]), clangFiles.clangExecutable().getAbsolutePath()); + } + } + + public static final class MaintenanceLockHolderProcess { + + private MaintenanceLockHolderProcess() { + } + + public static void main(String[] args) { + CacheFiles.withMaintenanceLock(Path.of(args[0]), () -> { + System.out.println("READY"); + System.out.flush(); + try { + System.in.read(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + System.out.println("DONE"); + System.out.flush(); + } + } + + public static final class MaintenanceLockProbeProcess { + + private MaintenanceLockProbeProcess() { + } + + public static void main(String[] args) { + var lockPath = Path.of(args[0], ".maintenance.lock"); + try (var channel = FileChannel.open(lockPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) { + var lock = channel.tryLock(); + if (lock != null) { + try (lock) { + System.out.println("ACQUIRED"); + System.out.flush(); + } + return; + } + + System.out.println("BLOCKED"); + System.out.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + try { + System.in.read(); + } catch (IOException e) { + throw new RuntimeException(e); + } + CacheFiles.withMaintenanceLock(Path.of(args[0]), () -> { + System.out.println("ENTERED"); + System.out.flush(); + }); + System.out.println("DONE"); + System.out.flush(); + } + } +} diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/CudaResourcesTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/CudaResourcesTest.java new file mode 100644 index 0000000000..09f27952d9 --- /dev/null +++ b/ClangAstParser/test/pt/up/fe/specs/clang/CudaResourcesTest.java @@ -0,0 +1,653 @@ +/** + * Copyright 2026 SPeCS. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import pt.up.fe.specs.clang.codeparser.CodeParser; +import pt.up.fe.specs.util.providers.FileResourceProvider; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class CudaResourcesTest { + + private static final String PLATFORM = "linux-x86_64"; + private static final String RELEASE = "12.3.2"; + private static final Duration TEST_TIMEOUT = Duration.ofSeconds(10); + + @TempDir + Path tempFolder; + + @Test + public void manifestSelectsRequiredComponentsAndValidatesMetadata() { + var manifest = CudaResources.parseManifest(manifestJson()); + + assertEquals(RELEASE, ClangAstWebResource.getCudaReleaseTag()); + assertEquals(RELEASE, manifest.releaseLabel()); + assertEquals("cuda", manifest.releaseProduct()); + assertEquals(List.of("cuda_cudart", "cuda_nvcc", "libcurand", "cuda_cccl"), + manifest.getRequiredPackages(PLATFORM).stream() + .map(CudaResources.CudaPackage::component) + .toList()); + assertEquals(CudaResources.NVIDIA_REDIST_ROOT + "cuda_cudart/linux-x86_64/cuda_cudart.tar.xz", + CudaResources.getArchiveResource(manifest.getRequiredPackages(PLATFORM).get(0)).getUrlString()); + assertEquals("redistrib_12.3.2.json", CudaResources.getManifestFilename(RELEASE)); + + assertThrows(RuntimeException.class, () -> CudaResources.parseManifest("")); + assertThrows(RuntimeException.class, + () -> CudaResources.parseManifest(manifestJson().replace(SHA256, "not-a-sha"))); + assertThrows(RuntimeException.class, + () -> CudaResources.parseManifest(manifestJson().replace( + "cuda_cudart/linux-x86_64/cuda_cudart.tar.xz", "../cuda_cudart.tar.xz"))); + assertThrows(RuntimeException.class, + () -> CudaResources.parseManifest(manifestJson().replace("\"size\": \"1\"", "\"size\": \"-1\""))); + + var wrongRelease = CudaResources.parseManifest(manifestJson() + .replace("\"release_label\": \"12.3.2\"", "\"release_label\": \"12.3.1\"")); + var releaseError = assertThrows(RuntimeException.class, () -> CudaResources.install( + tempFolder, tempFolder.resolve("wrong-release").toFile(), RELEASE, + new CudaResources.CudaPlatform(PLATFORM), wrongRelease, ignored -> { + throw new AssertionError("Archive downloads must not start for an invalid manifest"); + })); + assertTrue(releaseError.getMessage().contains("release label")); + + var wrongProduct = CudaResources.parseManifest(manifestJson() + .replace("\"release_product\": \"cuda\"", "\"release_product\": \"other\"")); + var productError = assertThrows(RuntimeException.class, () -> CudaResources.install( + tempFolder, tempFolder.resolve("wrong-product").toFile(), RELEASE, + new CudaResources.CudaPlatform(PLATFORM), wrongProduct, ignored -> { + throw new AssertionError("Archive downloads must not start for an invalid manifest"); + })); + assertTrue(productError.getMessage().contains("not a CUDA manifest")); + + var missingComponents = new LinkedHashMap<>(manifest.components()); + missingComponents.remove("cuda_cccl"); + var missingComponent = new CudaResources.NvidiaCudaManifest( + manifest.releaseDate(), manifest.releaseLabel(), manifest.releaseProduct(), missingComponents); + assertThrows(RuntimeException.class, () -> missingComponent.getRequiredPackages(PLATFORM)); + } + + @Test + public void manifestAcceptsHostWhenAllRequiredComponentsExposeACompatiblePlatform() { + var manifest = CudaResources.parseManifest(manifestJson()); + + assertEquals(PLATFORM, + CudaResources.getManifestPlatform(manifest, SupportedPlatform.LINUX, "amd64")); + } + + @Test + public void manifestRejectsHostWhenARequiredComponentLacksThePlatform() { + var manifest = CudaResources.parseManifest(manifestJson()); + var missingPlatformComponent = manifest.components().get("cuda_cccl"); + var archives = new LinkedHashMap<>(missingPlatformComponent.archives()); + archives.remove(PLATFORM); + var components = new LinkedHashMap<>(manifest.components()); + components.put("cuda_cccl", new CudaResources.NvidiaCudaComponent( + missingPlatformComponent.name(), missingPlatformComponent.version(), archives)); + var incompleteManifest = new CudaResources.NvidiaCudaManifest(manifest.releaseDate(), manifest.releaseLabel(), + manifest.releaseProduct(), components); + + var error = assertThrows(RuntimeException.class, + () -> CudaResources.getManifestPlatform(incompleteManifest, SupportedPlatform.LINUX, "amd64")); + assertTrue(error.getMessage().contains("linux (amd64)")); + assertTrue(error.getMessage().contains(PLATFORM)); + assertTrue(error.getMessage().contains("cuda_cccl")); + } + + @Test + public void supportDetectionReturnsFalseOnlyForAValidatedUnsupportedHost() throws IOException { + var unsupportedPlatform = SupportedPlatform.getCurrentPlatform().isWindows() + ? "linux-riscv64" + : "windows-x86_64"; + writeCachedManifest(manifestJson(unsupportedPlatform)); + + assertFalse(CudaResources.isSupportedPlatform(tempFolder)); + } + + @Test + public void supportDetectionPropagatesManifestAndCacheFailures() throws IOException { + writeCachedManifest("not-json"); + assertThrows(RuntimeException.class, () -> CudaResources.isSupportedPlatform(tempFolder)); + + var invalidManifestRoot = Files.createDirectory(tempFolder.resolve("invalid")).toAbsolutePath(); + writeCachedManifest(invalidManifestRoot, manifestJson() + .replace("\"release_product\": \"cuda\"", "\"release_product\": \"other\"")); + assertThrows(RuntimeException.class, () -> CudaResources.isSupportedPlatform(invalidManifestRoot)); + + var missingComponentRoot = Files.createDirectory(tempFolder.resolve("missing")).toAbsolutePath(); + writeCachedManifest(missingComponentRoot, manifestJson().replace("\"cuda_cccl\":", "\"missing\":")); + assertThrows(RuntimeException.class, () -> CudaResources.isSupportedPlatform(missingComponentRoot)); + + var cacheFile = tempFolder.resolve("cache-file"); + Files.writeString(cacheFile, "not-a-directory"); + assertThrows(RuntimeException.class, () -> CudaResources.isSupportedPlatform(cacheFile)); + } + + @Test + public void additionalCompatibleManifestPlatformNeedsNoJavaSupportWhitelist() { + var additionalPlatform = "linux-riscv64"; + var manifest = CudaResources.parseManifest(manifestJson(additionalPlatform)); + + assertEquals(additionalPlatform, + CudaResources.getManifestPlatform(manifest, SupportedPlatform.LINUX, "riscv64")); + } + + @Test + public void installationFetchesOnlyTheSelectedPlatformArchives() throws IOException { + var archives = createArchives(); + var manifest = addUnusedPlatforms(archives.manifest()); + var platform = new CudaResources.CudaPlatform(PLATFORM); + var platformFolder = CudaResources.getPlatformFolder(tempFolder, RELEASE, platform); + var writes = new AtomicInteger(); + + var installation = CudaResources.install(tempFolder, platformFolder, RELEASE, platform, manifest, + cudaPackage -> { + assertTrue(cudaPackage.archive().relativePath().contains("/" + PLATFORM + "/")); + var source = archives.files().get(cudaPackage.component()); + return copyingResource(source, source.getFileName().toString(), writes); + }); + + assertTrue(CudaResources.isCudaInstallation(installation, PLATFORM)); + assertEquals(CudaResources.REQUIRED_COMPONENTS.size(), writes.get()); + } + + @Test + public void archiveDownloadsRequireBothExpectedSizeAndSha256() throws IOException { + var source = Files.writeString(tempFolder.resolve("cuda_cudart.tar.xz"), "archive"); + var actualSize = Files.size(source); + var actualSha = sha256(source); + var platformFolder = CudaResources.getPlatformFolder(tempFolder, RELEASE, new CudaResources.CudaPlatform(PLATFORM)); + + var wrongSize = manifestForSingleArchive(source, actualSha, actualSize + 1); + var sizeError = assertThrows(RuntimeException.class, + () -> install(wrongSize, platformFolder, source, new AtomicInteger())); + assertTrue(sizeError.getMessage().contains("expected size")); + assertFalse(CudaResources.getArchiveFile(platformFolder, + wrongSize.getRequiredPackages(PLATFORM).get(0)).isFile()); + + var wrongSha = manifestForSingleArchive(source, "0".repeat(64), actualSize); + var shaError = assertThrows(RuntimeException.class, + () -> install(wrongSha, platformFolder, source, new AtomicInteger())); + assertTrue(shaError.getMessage().contains("expected SHA-256")); + } + + @Test + public void assembleSupportsTarXzAndZipPackages() throws IOException { + var archives = createArchives(); + var stagingFolder = Files.createDirectory(tempFolder.resolve("cudalib")); + + CudaResources.assemble(stagingFolder.toFile(), new CudaResources.CudaPlatform(PLATFORM), + downloadedPackages(archives)); + + assertEquals(PLATFORM, Files.readString(stagingFolder.resolve(CudaResources.PLATFORM_FILENAME))); + assertTrue(Files.isDirectory(stagingFolder.resolve("bin"))); + assertEquals("cuda.h", Files.readString(stagingFolder.resolve("include/cuda.h"))); + assertEquals("cuda_runtime.h", Files.readString(stagingFolder.resolve("include/cuda_runtime.h"))); + assertEquals("texture", Files.readString(stagingFolder.resolve("include/texture_fetch_functions.h"))); + assertEquals("curand", Files.readString(stagingFolder.resolve("include/curand_mtgp32_kernel.h"))); + assertEquals("target", Files.readString(stagingFolder.resolve("include/nv/target"))); + assertEquals("host_config", Files.readString(stagingFolder.resolve("include/crt/host_config.h"))); + assertEquals("libdevice", Files.readString(stagingFolder.resolve("nvvm/libdevice/libdevice.10.bc"))); + assertFalse(Files.exists(stagingFolder.resolve("bin/discarded"))); + assertFalse(Files.exists(stagingFolder.resolve("bin/discarded.exe"))); + assertTrue(CudaResources.isCudaInstallation(stagingFolder.toFile(), PLATFORM)); + } + + @Test + public void extractionRejectsTraversalEntries() throws IOException { + var traversalArchive = tempFolder.resolve("traversal.tar.xz"); + writeTarXz(traversalArchive, Map.of( + "cuda_cudart/include/../escape.h", bytes("escape"))); + var traversalPackage = new CudaResources.DownloadedPackage( + new CudaResources.CudaPackage("cuda_cudart", + new CudaResources.CudaArchive("cuda_cudart/linux-x86_64/cuda_cudart.tar.xz", SHA256, 1)), + traversalArchive.toFile()); + + assertThrows(RuntimeException.class, () -> CudaResources.assemble( + Files.createDirectory(tempFolder.resolve("traversal-out")).toFile(), + new CudaResources.CudaPlatform(PLATFORM), List.of(traversalPackage))); + assertFalse(Files.exists(tempFolder.resolve("escape.h"))); + + var driveArchive = tempFolder.resolve("drive.tar.xz"); + writeTarXz(driveArchive, Map.of("C:/escape.h", bytes("escape"))); + var drivePackage = new CudaResources.DownloadedPackage( + new CudaResources.CudaPackage("cuda_cudart", + new CudaResources.CudaArchive("cuda_cudart/linux-x86_64/cuda_cudart.tar.xz", SHA256, 1)), + driveArchive.toFile()); + assertThrows(RuntimeException.class, () -> CudaResources.assemble( + Files.createDirectory(tempFolder.resolve("drive-out")).toFile(), + new CudaResources.CudaPlatform(PLATFORM), List.of(drivePackage))); + } + + @Test + public void requiredComponentsAreStoredPerReleaseWithoutDeduplication() throws IOException { + var archives = createArchives(); + var firstRelease = CudaResources.getPlatformFolder(tempFolder, RELEASE, + new CudaResources.CudaPlatform(PLATFORM)); + var secondRelease = CudaResources.getPlatformFolder(tempFolder, "13.3.1", + new CudaResources.CudaPlatform(PLATFORM)); + + var first = install(archives, firstRelease, new AtomicInteger()); + var second = install(archives, secondRelease, new AtomicInteger()); + + assertTrue(CudaResources.isCudaInstallation(first, PLATFORM)); + assertTrue(CudaResources.isCudaInstallation(second, PLATFORM)); + assertNotEquals(CudaResources.getArchiveFile(firstRelease, + archives.manifest().getRequiredPackages(PLATFORM).get(0)).toPath(), + CudaResources.getArchiveFile(secondRelease, + archives.manifest().getRequiredPackages(PLATFORM).get(0)).toPath()); + } + + @Test + public void existingValidInstallationIsReusedAndUsageIsRefreshed() throws IOException { + var platform = new CudaResources.CudaPlatform(hostPlatform()); + var platformFolder = CudaResources.getPlatformFolder(tempFolder, RELEASE, platform); + var installation = CudaResources.getInstallationFolder(platformFolder); + writeValidInstallation(installation.toPath(), PLATFORM); + var old = FileTime.from(Instant.now().minus(Duration.ofDays(61))); + Files.setLastModifiedTime(platformFolder.toPath().getParent(), old); + + var parser = CodeParser.newInstance(); + parser.set(CodeParser.DUMPER_FOLDER, tempFolder.toFile()); + var result = new ClangResources(parser).getBuiltinCudaLib(); + + assertEquals(installation.getAbsoluteFile(), result.getAbsoluteFile()); + assertTrue(Files.getLastModifiedTime(platformFolder.toPath().getParent()).toInstant() + .isAfter(Instant.now().minus(Duration.ofDays(1)))); + } + + @Test + public void invalidPublishedInstallationFailsWithoutRepair() throws IOException { + var platform = new CudaResources.CudaPlatform(hostPlatform()); + var platformFolder = CudaResources.getPlatformFolder(tempFolder, RELEASE, platform); + var installation = CudaResources.getInstallationFolder(platformFolder); + Files.createDirectories(installation.toPath()); + Files.writeString(installation.toPath().resolve("sentinel"), "do not repair"); + + var parser = CodeParser.newInstance(); + parser.set(CodeParser.DUMPER_FOLDER, tempFolder.toFile()); + var error = assertThrows(RuntimeException.class, () -> new ClangResources(parser).getBuiltinCudaLib()); + + assertTrue(error.getMessage().contains(installation.getAbsolutePath())); + assertTrue(error.getMessage().contains("delete this directory manually to regenerate")); + assertEquals("do not repair", Files.readString(installation.toPath().resolve("sentinel"))); + } + + @Test + public void oldPartialReleaseIsProtectedWhileInitializationContinues() throws Exception { + var platformFolder = CudaResources.getPlatformFolder(tempFolder, RELEASE, + new CudaResources.CudaPlatform(PLATFORM)); + var releaseFolder = platformFolder.toPath().getParent(); + Files.createDirectories(platformFolder.toPath().resolve("partial")); + Files.writeString(platformFolder.toPath().resolve("partial/manifest-download"), "in progress"); + var old = FileTime.from(Instant.now().minus(Duration.ofDays(61))); + Files.setLastModifiedTime(releaseFolder, old); + Files.setLastModifiedTime(platformFolder.toPath(), old); + + var claimed = new CountDownLatch(1); + var allowInitializationToFinish = new CountDownLatch(1); + var executor = Executors.newFixedThreadPool(2); + + try { + var initialization = executor.submit(() -> { + CudaResources.claimInUse(tempFolder, platformFolder); + claimed.countDown(); + awaitLatch(allowInitializationToFinish); + }); + assertTrue(claimed.await(TEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)); + + var cleanup = executor.submit(() -> CacheFiles.deleteStaleDirectories(tempFolder, + tempFolder.resolve("cuda"), Instant.now().minus(Duration.ofDays(60)), null)); + cleanup.get(TEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + + assertTrue(Files.isDirectory(releaseFolder)); + assertTrue(Files.isDirectory(platformFolder.toPath())); + assertTrue(Files.getLastModifiedTime(releaseFolder).toInstant() + .isAfter(Instant.now().minus(Duration.ofDays(1)))); + assertTrue(Files.getLastModifiedTime(platformFolder.toPath()).toInstant() + .isAfter(Instant.now().minus(Duration.ofDays(1)))); + + allowInitializationToFinish.countDown(); + initialization.get(TEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } finally { + allowInitializationToFinish.countDown(); + executor.shutdownNow(); + executor.awaitTermination(TEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } + } + + @Test + public void concurrentPublicationLeavesOneValidInstallation() throws Exception { + var archives = createArchives(); + var platform = new CudaResources.CudaPlatform(PLATFORM); + var platformFolder = CudaResources.getPlatformFolder(tempFolder, RELEASE, platform); + var writes = new AtomicInteger(); + var executor = Executors.newFixedThreadPool(4); + var futures = new ArrayList>(); + + try { + for (int i = 0; i < 4; i++) { + futures.add(executor.submit(() -> install(archives, platformFolder, writes))); + } + + for (var future : futures) { + assertEquals(CudaResources.getInstallationFolder(platformFolder).getAbsoluteFile(), + future.get(TEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS).getAbsoluteFile()); + } + } finally { + executor.shutdownNow(); + executor.awaitTermination(TEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } + + assertTrue(CudaResources.isCudaInstallation(CudaResources.getInstallationFolder(platformFolder), PLATFORM)); + try (var children = Files.list(platformFolder.toPath())) { + assertTrue(children.noneMatch(path -> path.getFileName().toString().startsWith(".cudalib.tmp-"))); + } + try (var children = Files.list(platformFolder.toPath().resolve("archives/cuda_cudart"))) { + assertTrue(children.noneMatch(path -> path.getFileName().toString().startsWith(".cuda_cudart"))); + } + assertTrue(writes.get() >= 4); + } + + @Test + public void staleCudaReleasesAreRemovedAfterSixtyDays() throws IOException { + var platform = new CudaResources.CudaPlatform(hostPlatform()); + var currentFolder = CudaResources.getPlatformFolder(tempFolder, RELEASE, platform); + var currentInstallation = CudaResources.getInstallationFolder(currentFolder); + writeValidInstallation(currentInstallation.toPath(), PLATFORM); + + var staleFolder = CudaResources.getPlatformFolder(tempFolder, "11.8.0", platform); + Files.createDirectories(staleFolder.toPath()); + Files.setLastModifiedTime(staleFolder.toPath().getParent(), + FileTime.from(Instant.now().minus(Duration.ofDays(61)))); + + var parser = CodeParser.newInstance(); + parser.set(CodeParser.DUMPER_FOLDER, tempFolder.toFile()); + new ClangResources(parser).getBuiltinCudaLib(); + + assertTrue(currentInstallation.isDirectory()); + assertFalse(staleFolder.getParentFile().exists()); + } + + private File install(CudaResources.NvidiaCudaManifest manifest, File platformFolder, Path source, + AtomicInteger writes) { + return CudaResources.install(tempFolder, platformFolder, RELEASE, + new CudaResources.CudaPlatform(PLATFORM), manifest, + cudaPackage -> copyingResource(source, + source.getFileName().toString(), writes)); + } + + private File install(ArchiveSet archives, File platformFolder, AtomicInteger writes) { + return CudaResources.install(tempFolder, platformFolder, RELEASE, + new CudaResources.CudaPlatform(PLATFORM), archives.manifest(), + cudaPackage -> { + var source = archives.files().get(cudaPackage.component()); + return copyingResource(source, source.getFileName().toString(), writes); + }); + } + + private ArchiveSet createArchives() throws IOException { + var files = new LinkedHashMap(); + var cudart = tempFolder.resolve("cuda_cudart.tar.xz"); + writeTarXz(cudart, Map.of( + "cuda_cudart/include/cuda.h", bytes("cuda.h"), + "cuda_cudart/include/cuda_runtime.h", bytes("cuda_runtime.h"), + "cuda_cudart/include/texture_fetch_functions.h", bytes("texture"), + "cuda_cudart/bin/discarded", bytes("discarded"))); + files.put("cuda_cudart", cudart); + + var nvcc = tempFolder.resolve("cuda_nvcc.zip"); + writeZip(nvcc, Map.of( + "cuda_nvcc/include/crt/host_config.h", bytes("host_config"), + "cuda_nvcc/nvvm/libdevice/libdevice.10.bc", bytes("libdevice"), + "cuda_nvcc/bin/discarded.exe", bytes("discarded"))); + files.put("cuda_nvcc", nvcc); + + var curand = tempFolder.resolve("libcurand.tar.xz"); + writeTarXz(curand, Map.of( + "libcurand/include/curand_mtgp32_kernel.h", bytes("curand"))); + files.put("libcurand", curand); + + var cccl = tempFolder.resolve("cuda_cccl.zip"); + writeZip(cccl, Map.of("cuda_cccl/include/nv/target", bytes("target"))); + files.put("cuda_cccl", cccl); + + var components = new LinkedHashMap(); + for (var component : CudaResources.REQUIRED_COMPONENTS) { + var archive = files.get(component); + var archivePath = component + "/linux-x86_64/" + archive.getFileName(); + var cudaArchive = new CudaResources.CudaArchive(archivePath, sha256(archive), Files.size(archive)); + components.put(component, new CudaResources.NvidiaCudaComponent(component, RELEASE, + Map.of(PLATFORM, cudaArchive))); + } + + return new ArchiveSet(new CudaResources.NvidiaCudaManifest("2024-01-02", RELEASE, "cuda", components), files); + } + + private List downloadedPackages(ArchiveSet archives) { + return archives.manifest().getRequiredPackages(PLATFORM).stream() + .map(cudaPackage -> new CudaResources.DownloadedPackage(cudaPackage, + archives.files().get(cudaPackage.component()).toFile())) + .toList(); + } + + private CudaResources.NvidiaCudaManifest manifestForSingleArchive(Path source, String sha256, long size) { + var components = new LinkedHashMap(); + for (var component : CudaResources.REQUIRED_COMPONENTS) { + var archiveName = component.equals("cuda_cudart") ? "cuda_cudart.tar.xz" : source.getFileName().toString(); + var relativePath = component + "/linux-x86_64/" + archiveName; + components.put(component, new CudaResources.NvidiaCudaComponent(component, RELEASE, + Map.of(PLATFORM, new CudaResources.CudaArchive(relativePath, sha256, size)))); + } + + return new CudaResources.NvidiaCudaManifest("2024-01-02", RELEASE, "cuda", components); + } + + private CudaResources.NvidiaCudaManifest addUnusedPlatforms(CudaResources.NvidiaCudaManifest manifest) { + var components = new LinkedHashMap(); + for (var entry : manifest.components().entrySet()) { + var selectedArchive = entry.getValue().archives().get(PLATFORM); + var archives = new LinkedHashMap<>(entry.getValue().archives()); + for (var unusedPlatform : List.of("linux-riscv64", "windows-x86_64")) { + archives.put(unusedPlatform, new CudaResources.CudaArchive( + entry.getKey() + "/" + unusedPlatform + "/unused.tar.xz", + selectedArchive.sha256(), selectedArchive.size())); + } + components.put(entry.getKey(), new CudaResources.NvidiaCudaComponent( + entry.getValue().name(), entry.getValue().version(), archives)); + } + + return new CudaResources.NvidiaCudaManifest(manifest.releaseDate(), manifest.releaseLabel(), + manifest.releaseProduct(), components); + } + + private void writeValidInstallation(Path installation, String platform) throws IOException { + Files.createDirectories(installation.resolve("bin")); + Files.writeString(installation.resolve(CudaResources.PLATFORM_FILENAME), platform); + for (var requiredFile : List.of( + "include/cuda.h", + "include/cuda_runtime.h", + "include/texture_fetch_functions.h", + "include/curand_mtgp32_kernel.h", + "include/nv/target", + "include/crt/host_config.h", + "nvvm/libdevice/libdevice.10.bc")) { + var file = installation.resolve(requiredFile); + Files.createDirectories(file.getParent()); + Files.writeString(file, requiredFile); + } + } + + private FileResourceProvider copyingResource(Path source, String filename, AtomicInteger writes) { + return new FileResourceProvider() { + @Override + public File write(java.io.File folder) { + writes.incrementAndGet(); + try { + var destination = folder.toPath().resolve(filename); + Files.copy(source, destination); + return destination.toFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public String version() { + return "test"; + } + + @Override + public String getFilename() { + return filename; + } + }; + } + + private static String hostPlatform() { + return PLATFORM; + } + + private void writeCachedManifest(String json) throws IOException { + writeCachedManifest(tempFolder, json); + } + + private void writeCachedManifest(Path cacheRoot, String json) throws IOException { + var releaseFolder = cacheRoot.resolve("cuda").resolve(ClangAstWebResource.getCudaReleaseTag()); + Files.createDirectories(releaseFolder); + Files.writeString(releaseFolder.resolve(CudaResources.getManifestFilename(RELEASE)), json); + } + + private static void writeTarXz(Path archive, Map files) throws IOException { + try (OutputStream output = Files.newOutputStream(archive); + var xzOutput = new XZCompressorOutputStream(output); + var tarOutput = new TarArchiveOutputStream(xzOutput)) { + tarOutput.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); + for (var file : files.entrySet()) { + var entry = new TarArchiveEntry(file.getKey()); + entry.setSize(file.getValue().length); + tarOutput.putArchiveEntry(entry); + tarOutput.write(file.getValue()); + tarOutput.closeArchiveEntry(); + } + } + } + + private static void writeZip(Path archive, Map files) throws IOException { + try (OutputStream output = Files.newOutputStream(archive); + var zipOutput = new ZipArchiveOutputStream(output)) { + for (var file : files.entrySet()) { + var entry = new ZipArchiveEntry(file.getKey()); + zipOutput.putArchiveEntry(entry); + zipOutput.write(file.getValue()); + zipOutput.closeArchiveEntry(); + } + } + } + + private static String manifestJson() { + return manifestJson(PLATFORM); + } + + private static String manifestJson(String platform) { + return """ + { + "release_date": "2024-01-02", + "release_label": "12.3.2", + "release_product": "cuda", + "cuda_cudart": %s, + "cuda_nvcc": %s, + "libcurand": %s, + "cuda_cccl": %s + } + """.formatted( + component("CUDA Runtime", platform, "cuda_cudart/" + platform + "/cuda_cudart.tar.xz"), + component("CUDA NVCC", platform, "cuda_nvcc/" + platform + "/cuda_nvcc.tar.xz"), + component("cuRAND", platform, "libcurand/" + platform + "/libcurand.tar.xz"), + component("CCCL", platform, "cuda_cccl/" + platform + "/cuda_cccl.tar.xz")); + } + + private static String component(String name, String platform, String relativePath) { + return """ + { + "name": "%s", + "version": "12.3.101", + "%s": { + "relative_path": "%s", + "sha256": "%s", + "size": "1" + } + } + """.formatted(name, platform, relativePath, SHA256); + } + + private static byte[] bytes(String value) { + return value.getBytes(StandardCharsets.UTF_8); + } + + private static String sha256(Path file) throws IOException { + try { + return java.util.HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256") + .digest(Files.readAllBytes(file))); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + private static final String SHA256 = "0".repeat(64); + + private static void awaitLatch(CountDownLatch latch) { + try { + if (!latch.await(TEST_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)) { + throw new AssertionError("Timed out waiting for CUDA initialization test coordination"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } + + private record ArchiveSet(CudaResources.NvidiaCudaManifest manifest, Map files) { + } +} diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/parser/CxxCudaTester.java b/ClangAstParser/test/pt/up/fe/specs/clang/parser/CxxCudaTester.java index 45fdfffce8..fde8a56bcc 100644 --- a/ClangAstParser/test/pt/up/fe/specs/clang/parser/CxxCudaTester.java +++ b/ClangAstParser/test/pt/up/fe/specs/clang/parser/CxxCudaTester.java @@ -16,7 +16,7 @@ import java.util.Arrays; import java.util.List; -import pt.up.fe.specs.lang.SpecsPlatforms; +import pt.up.fe.specs.clang.ClangResources; public class CxxCudaTester extends AClangAstTester { @@ -28,8 +28,7 @@ public CxxCudaTester(List files) { // super("cxx/cuda", files, Arrays.asList("-std=cuda")); super("cxx/cuda", files); - // Windows currently not supported - if (SpecsPlatforms.isWindows()) { + if (!ClangResources.isBuiltinCudaSupported()) { doNotRun(); } diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxCudaTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxCudaTest.java index 1a6b37d3f7..7d45f6770f 100644 --- a/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxCudaTest.java +++ b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxCudaTest.java @@ -15,19 +15,25 @@ import org.junit.jupiter.api.Test; +import pt.up.fe.specs.clang.ClangAstKeys; +import pt.up.fe.specs.clang.LibcMode; import pt.up.fe.specs.clang.parser.CxxCudaTester; -/** - * Disabled tests, they are failing in the CI server. Even when passing the --cuda-path built-in library, the parser - * fails to find the CUDA library. - * - * @author JBispo - * - */ +/** Verifies built-in CUDA parsing through the pinned NVIDIA redistribution packages. */ public class CxxCudaTest { @Test - public void testAtomicAdd() { - new CxxCudaTester("atomicAdd.cu").test(); + public void testAtomicAddWithBuiltinLibc() { + new CxxCudaTester("atomicAdd.cu") + .set(ClangAstKeys.LIBC_CXX_MODE, LibcMode.BUILTIN_AND_LIBC) + .test(); + } + + @Test + public void testAtomicAddWithSystemLibc() { + new CxxCudaTester("atomicAdd.cu") + .set(ClangAstKeys.LIBC_CXX_MODE, LibcMode.SYSTEM) + .onePass() + .test(); } @Test diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxTest.java index b8cdfe5726..7de8c90424 100644 --- a/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxTest.java +++ b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/CxxTest.java @@ -287,6 +287,13 @@ public void testStrings() { new CxxTester("strings.cpp").test(); } + @Test + public void testUnevaluatedStrings() { + new CxxTester("unevaluated_strings.cpp") + .addFlags("-std=c++26") + .test(); + } + // -Xclang-ast-dump-nostdinc-nocudalib-nocudainc--cuda-gpu-arch=sm_30 // "--cuda-device-only" diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/InitializationStyleTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/InitializationStyleTest.java new file mode 100644 index 0000000000..5e1f99532b --- /dev/null +++ b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/InitializationStyleTest.java @@ -0,0 +1,58 @@ +/** + * Copyright 2026 SPeCS. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang.parser.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import pt.up.fe.specs.clang.codeparser.CodeParser; +import pt.up.fe.specs.clava.ast.decl.VarDecl; +import pt.up.fe.specs.clava.ast.decl.enums.InitializationStyle; +import pt.up.fe.specs.clava.ast.extra.App; +import pt.up.fe.specs.util.SpecsIo; +import pt.up.fe.specs.util.SpecsSystem; + +public class InitializationStyleTest { + + @TempDir + Path tempFolder; + + @Test + public void parenthesizedListInitializationKeepsAllArguments() { + SpecsSystem.programStandardInit(); + + File sourceFile = SpecsIo.resourceCopy("cxx/paren_list_initialization.cpp", tempFolder.toFile(), false, true); + App app = CodeParser.newInstance().parse(List.of(sourceFile), List.of("-std=c++20")); + + VarDecl point = app.getDescendants(VarDecl.class).stream() + .filter(varDecl -> varDecl.getDeclName().equals("point")) + .findFirst() + .orElseThrow(); + + assertEquals(InitializationStyle.ParenListInit, point.get(VarDecl.INIT_STYLE)); + assertEquals("Point point(1, 2)", point.getCode()); + } + + @Test + public void javascriptInitializationStyleNamesRemainCompatible() { + assertEquals("callinit", InitializationStyle.CALL_INIT.getString()); + assertEquals("listinit", InitializationStyle.LIST_INIT.getString()); + } +} diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/SourceLocationsTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/SourceLocationsTest.java new file mode 100644 index 0000000000..c9e24c6c84 --- /dev/null +++ b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/SourceLocationsTest.java @@ -0,0 +1,88 @@ +/** + * Copyright 2026 SPeCS. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang.parser.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; +import java.util.function.Predicate; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import pt.up.fe.specs.clang.codeparser.CodeParser; +import pt.up.fe.specs.clava.ClavaNode; +import pt.up.fe.specs.clava.SourceRange; +import pt.up.fe.specs.clava.ast.decl.TemplateTypeParmDecl; +import pt.up.fe.specs.clava.ast.decl.VarDecl; +import pt.up.fe.specs.clava.ast.extra.App; +import pt.up.fe.specs.util.SpecsIo; +import pt.up.fe.specs.util.SpecsSystem; + +public class SourceLocationsTest { + + private static final String RESOURCE = "cxx/source_locations.cpp"; + + @TempDir + Path tempFolder; + + @Test + public void sourceLocationsUseRealFileCoordinates() { + SpecsSystem.programStandardInit(); + + File sourceFile = SpecsIo.resourceCopy(RESOURCE, tempFolder.toFile(), false, true); + App app = CodeParser.newInstance().parse(List.of(sourceFile), List.of("-std=c++11")); + + VarDecl ordinary = find(app.getDescendants(VarDecl.class), varDecl -> varDecl.getDeclName().equals("ordinary")); + assertRange(ordinary, false, 7, 1, 7, 16); + + VarDecl macro = find(app.getDescendants(VarDecl.class), varDecl -> varDecl.getDeclName().equals("macro_value")); + assertRange(macro, true, 6, 1, 6, 24); + assertRange(macro.getInit().orElseThrow(), true, 6, 1, 6, 24); + + VarDecl pastedReference = find(app.getDescendants(VarDecl.class), + varDecl -> varDecl.getDeclName().equals("pasted_reference")); + assertRange(pastedReference.getInit().orElseThrow(), true, 9, 24, 9, 36); + + TemplateTypeParmDecl templateParameter = find(app.getDescendantsAndFields(TemplateTypeParmDecl.class), + parameter -> parameter.getDeclName().equals("BinaryType")); + assertRange(templateParameter, false, 16, 11, 16, 54); + } + + private static T find(List nodes, Predicate predicate) { + return nodes.stream() + .filter(predicate) + .findFirst() + .orElseThrow(); + } + + private static void assertRange(ClavaNode node, boolean isMacro, int startLine, int startColumn, int endLine, + int endColumn) { + + SourceRange location = node.getLocation(); + + assertEquals("source_locations.cpp", location.getFilename()); + assertEquals("source_locations.cpp", Path.of(location.getStartFilepath()).getFileName().toString()); + assertEquals("source_locations.cpp", Path.of(location.getEndFilepath()).getFileName().toString()); + assertEquals(startLine, location.getStartLine()); + assertEquals(startColumn, location.getStartCol()); + assertEquals(endLine, location.getEndLine()); + assertEquals(endColumn, location.getEndCol()); + assertEquals(isMacro, node.get(ClavaNode.IS_MACRO)); + assertFalse(location.toString().contains("")); + } +} diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/UnaryTransformTypeTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/UnaryTransformTypeTest.java new file mode 100644 index 0000000000..27d54bd00e --- /dev/null +++ b/ClangAstParser/test/pt/up/fe/specs/clang/parser/tests/UnaryTransformTypeTest.java @@ -0,0 +1,85 @@ +/** + * Copyright 2026 SPeCS. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang.parser.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import pt.up.fe.specs.clang.codeparser.CodeParser; +import pt.up.fe.specs.clava.ast.extra.App; +import pt.up.fe.specs.clava.ast.type.Type; +import pt.up.fe.specs.clava.ast.type.UnaryTransformType; +import pt.up.fe.specs.clava.ast.type.enums.UnaryTransformTypeKind; +import pt.up.fe.specs.util.SpecsSystem; + +public class UnaryTransformTypeTest { + + private static final String SOURCE = """ + template + struct Dependent { + using type = __underlying_type(T); + }; + + enum Resolved { Value }; + using ResolvedType = __underlying_type(Resolved); + """; + + @TempDir + Path tempFolder; + + @Test + public void dependentTransformsMayHaveNoUnderlyingType() throws IOException { + SpecsSystem.programStandardInit(); + + File sourceFile = tempFolder.resolve("unary_transform_type.cpp").toFile(); + Files.writeString(sourceFile.toPath(), SOURCE); + + App app = CodeParser.newInstance().parse(List.of(sourceFile), List.of("-std=c++11")); + + List transforms = app.getDescendantsAndFields(UnaryTransformType.class).stream() + .filter(transform -> transform.get(UnaryTransformType.KIND) == UnaryTransformTypeKind.EnumUnderlyingType) + .toList(); + + assertEquals(2, transforms.size()); + + UnaryTransformType dependentTransform = transforms.stream() + .filter(transform -> transform.getUnderlyingType().isEmpty()) + .findFirst() + .orElseThrow(); + + assertNotNull(dependentTransform.getBaseType()); + assertEquals(1, dependentTransform.getNodeFields().size()); + assertTrue(dependentTransform.getNodeFields().contains(dependentTransform.getBaseType())); + + UnaryTransformType resolvedTransform = transforms.stream() + .filter(transform -> transform.getUnderlyingType().isPresent()) + .findFirst() + .orElseThrow(); + + Type resolvedUnderlyingType = resolvedTransform.getUnderlyingType().orElseThrow(); + assertNotNull(resolvedTransform.getBaseType()); + assertTrue(resolvedTransform.getNodeFields().contains(resolvedTransform.getBaseType())); + assertTrue(resolvedTransform.getNodeFields().contains(resolvedUnderlyingType)); + } +} diff --git a/ClangAstParser/test/pt/up/fe/specs/clang/parsers/ClavaNodesTest.java b/ClangAstParser/test/pt/up/fe/specs/clang/parsers/ClavaNodesTest.java new file mode 100644 index 0000000000..f4a42736af --- /dev/null +++ b/ClangAstParser/test/pt/up/fe/specs/clang/parsers/ClavaNodesTest.java @@ -0,0 +1,71 @@ +/** + * Copyright 2026 SPeCS. + *

    + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package pt.up.fe.specs.clang.parsers; + +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.suikasoft.jOptions.Interfaces.DataStore; + +import pt.up.fe.specs.clava.ast.expr.Expr; +import pt.up.fe.specs.clava.context.ClavaContext; + +public class ClavaNodesTest { + + @Test + public void optionalNodeResolvesPresentNode() { + var context = new ClavaContext(); + var factory = context.getFactory(); + var clavaNodes = new ClavaNodes(factory); + DataStore data = factory.newDataStore(Expr.class); + var type = factory.nullType(); + + clavaNodes.getNodes().put("type-id", type); + clavaNodes.queueSetOptionalNode(data, Expr.TYPE, "type-id"); + clavaNodes.getQueuedActions().forEach(Runnable::run); + + assertSame(type, data.get(Expr.TYPE).orElseThrow()); + } + + @Test + public void optionalNodeUsesEmptyForExplicitNullId() { + var context = new ClavaContext(); + var factory = context.getFactory(); + var clavaNodes = new ClavaNodes(factory); + DataStore data = factory.newDataStore(Expr.class); + + clavaNodes.queueSetOptionalNode(data, Expr.TYPE, "nullptr_type"); + clavaNodes.getQueuedActions().forEach(Runnable::run); + + assertTrue(data.get(Expr.TYPE).isEmpty()); + } + + @Test + public void optionalNodeRejectsUnresolvedNodeId() { + var context = new ClavaContext(); + var factory = context.getFactory(); + var clavaNodes = new ClavaNodes(factory); + DataStore data = factory.newDataStore(Expr.class); + + clavaNodes.queueSetOptionalNode(data, Expr.TYPE, "missing-id"); + + var exception = assertThrows(NullPointerException.class, + () -> clavaNodes.getQueuedActions().forEach(Runnable::run)); + + assertTrue(exception.getMessage().contains("Could not resolve optional node 'missing-id'")); + assertTrue(exception.getMessage().contains("key 'type'")); + } +} diff --git a/Clava-JS/.gitignore b/Clava-JS/.gitignore index 60a7a887ce..d8f403bdc2 100644 --- a/Clava-JS/.gitignore +++ b/Clava-JS/.gitignore @@ -1,7 +1,5 @@ ##### User-added ##### woven_code/ -/api -/code package-lock.json java-binaries diff --git a/Clava-JS/README.md b/Clava-JS/README.md index 0dd99989b4..156f76e401 100644 --- a/Clava-JS/README.md +++ b/Clava-JS/README.md @@ -2,7 +2,7 @@ Clava source-to-source compiler running on top of Node.js. -Current version only works on Node 20 and 22. +Current version works on Node >=24. To test Clava-JS you can try the [Clava project template](https://github.com/specs-feup/clava-project-template). @@ -35,21 +35,21 @@ Starting from the `workspace` directory, execute the following commands to build ```bash npm install -npm run build -w lara-framework/Lara-JS -npm run build -w clava/Clava-JS -npm install -cd clava/ClavaWeaver -gradle installDist -cd ../.. +gradle -p clava clavaJsBuild ``` -Finally, copy the JARs in the folder `./clava/ClavaWeaver/build/install/ClavaWeaver/lib` into a new folder called java-binaries in `./clava/Clava-JS`: +The `clavaJsBuild` task builds Lara-JS, runs `ClavaWeaver:installDist`, and synchronizes its complete distribution into `./clava/Clava-JS/java-binaries`. The generated directory is refreshed automatically, including when `installDist` is invoked directly, so do not copy or edit its contents manually. + +Clava-JS tests invoked through the combined Gradle build always run after this synchronization. Local `npm pack` and `npm publish` also validate that `java-binaries` is a real, populated directory before creating a package. + +To run the Java and Clava-JS tests from one place and generate the merged Java coverage report: ```bash -mkdir clava/Clava-JS/java-binaries -cp -r ./clava/ClavaWeaver/build/install/ClavaWeaver/lib ./clava/Clava-JS/java-binaries +gradle -p clava check clavaMergedJacocoReport ``` +The merged report is written to `./clava/build/reports/jacoco/clavaMergedJacocoReport/html/index.html`. It combines normal Gradle JaCoCo execution data with the JaCoCo data captured from the JVM embedded in Clava-JS tests. + Install the package globally: ```bash diff --git a/Clava-JS/src-api/Issues.test.ts b/Clava-JS/api/Issues.test.ts similarity index 87% rename from Clava-JS/src-api/Issues.test.ts rename to Clava-JS/api/Issues.test.ts index dd73aa1cdc..d6e3a89fdb 100644 --- a/Clava-JS/src-api/Issues.test.ts +++ b/Clava-JS/api/Issues.test.ts @@ -1,10 +1,10 @@ import { registerSourceCode, registerSourceCodes, -} from "@specs-feup/lara/jest/jestHelpers.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { FunctionJp } from "@specs-feup/clava/api/Joinpoints.js"; -import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js"; +} from "@specs-feup/lara/vitest/weaverTestHelpers.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { FunctionJp } from "./Joinpoints.ts"; +import ClavaJoinPoints from "./clava/ClavaJoinPoints.ts"; const code187 = ` int foo(int a); diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/api/Joinpoints.ts similarity index 82% rename from Clava-JS/src-api/Joinpoints.ts rename to Clava-JS/api/Joinpoints.ts index e7e764a90b..98997a143d 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/api/Joinpoints.ts @@ -1,5 +1,5 @@ /////////////////////////////////////////////////// -// This file is generated by build-interfaces.js // +// This file is generated by build-interfaces.ts // /////////////////////////////////////////////////// import { @@ -7,132 +7,132 @@ import { registerJoinpointMapper, wrapJoinPoint, unwrapJoinPoint, -} from "@specs-feup/lara/api/LaraJoinPoint.js"; + InsertPosition, +} from "@specs-feup/lara/api/LaraJoinPoint.ts"; type PrivateMapper = { "Joinpoint": typeof Joinpoint, - "Attribute": typeof Attribute, - "ClavaException": typeof ClavaException, - "Comment": typeof Comment, - "Decl": typeof Decl, "Empty": typeof Empty, - "Expression": typeof Expression, + "Program": typeof Program, "FileJp": typeof FileJp, - "ImplicitValue": typeof ImplicitValue, - "Include": typeof Include, - "InitList": typeof InitList, - "Literal": typeof Literal, - "MemberAccess": typeof MemberAccess, + "Decl": typeof Decl, "NamedDecl": typeof NamedDecl, - "NewExpr": typeof NewExpr, - "Op": typeof Op, - "ParenExpr": typeof ParenExpr, - "Pragma": typeof Pragma, - "Program": typeof Program, + "Declarator": typeof Declarator, + "Include": typeof Include, "RecordJp": typeof RecordJp, - "Statement": typeof Statement, + "Field": typeof Field, "Struct": typeof Struct, - "Switch": typeof Switch, - "SwitchCase": typeof SwitchCase, - "Tag": typeof Tag, - "TernaryOp": typeof TernaryOp, - "This": typeof This, - "Type": typeof Type, + "Class": typeof Class, + "Vardecl": typeof Vardecl, "TypedefNameDecl": typeof TypedefNameDecl, - "TypedefType": typeof TypedefType, - "UnaryExprOrType": typeof UnaryExprOrType, - "UnaryOp": typeof UnaryOp, - "UndefinedType": typeof UndefinedType, - "Varref": typeof Varref, - "WrapperStmt": typeof WrapperStmt, + "TypedefDecl": typeof TypedefDecl, + "EnumDecl": typeof EnumDecl, + "EnumeratorDecl": typeof EnumeratorDecl, + "LabelDecl": typeof LabelDecl, "AccessSpecifier": typeof AccessSpecifier, - "AdjustedType": typeof AdjustedType, - "ArrayAccess": typeof ArrayAccess, - "ArrayType": typeof ArrayType, - "AsmStmt": typeof AsmStmt, - "BinaryOp": typeof BinaryOp, - "BoolLiteral": typeof BoolLiteral, - "Break": typeof Break, - "BuiltinType": typeof BuiltinType, - "Call": typeof Call, + "Param": typeof Param, + "FunctionJp": typeof FunctionJp, + "Method": typeof Method, + "Pragma": typeof Pragma, + "Marker": typeof Marker, + "Tag": typeof Tag, + "Omp": typeof Omp, + "Statement": typeof Statement, + "Scope": typeof Scope, + "Body": typeof Body, + "Loop": typeof Loop, + "If": typeof If, + "WrapperStmt": typeof WrapperStmt, + "ReturnStmt": typeof ReturnStmt, + "Switch": typeof Switch, + "SwitchCase": typeof SwitchCase, "Case": typeof Case, - "Cast": typeof Cast, - "CilkSpawn": typeof CilkSpawn, - "CilkSync": typeof CilkSync, - "Class": typeof Class, - "Continue": typeof Continue, - "CudaKernelCall": typeof CudaKernelCall, - "DeclStmt": typeof DeclStmt, - "Declarator": typeof Declarator, "Default": typeof Default, - "DeleteExpr": typeof DeleteExpr, - "ElaboratedType": typeof ElaboratedType, - "EmptyStmt": typeof EmptyStmt, - "EnumDecl": typeof EnumDecl, - "EnumeratorDecl": typeof EnumeratorDecl, + "DeclStmt": typeof DeclStmt, "ExprStmt": typeof ExprStmt, - "Field": typeof Field, - "FloatLiteral": typeof FloatLiteral, - "FunctionJp": typeof FunctionJp, - "FunctionType": typeof FunctionType, "GotoStmt": typeof GotoStmt, - "If": typeof If, - "IncompleteArrayType": typeof IncompleteArrayType, - "IntLiteral": typeof IntLiteral, - "LabelDecl": typeof LabelDecl, "LabelStmt": typeof LabelStmt, - "Loop": typeof Loop, - "Marker": typeof Marker, + "EmptyStmt": typeof EmptyStmt, + "Continue": typeof Continue, + "Break": typeof Break, + "AsmStmt": typeof AsmStmt, + "Expression": typeof Expression, + "Call": typeof Call, "MemberCall": typeof MemberCall, - "Method": typeof Method, - "Omp": typeof Omp, - "ParenType": typeof ParenType, + "CudaKernelCall": typeof CudaKernelCall, + "Op": typeof Op, + "BinaryOp": typeof BinaryOp, + "UnaryOp": typeof UnaryOp, + "TernaryOp": typeof TernaryOp, + "NewExpr": typeof NewExpr, + "DeleteExpr": typeof DeleteExpr, + "Varref": typeof Varref, + "Cast": typeof Cast, + "ParenExpr": typeof ParenExpr, + "ArrayAccess": typeof ArrayAccess, + "MemberAccess": typeof MemberAccess, + "UnaryExprOrType": typeof UnaryExprOrType, + "This": typeof This, + "Literal": typeof Literal, + "IntLiteral": typeof IntLiteral, + "FloatLiteral": typeof FloatLiteral, + "BoolLiteral": typeof BoolLiteral, + "InitList": typeof InitList, + "ImplicitValue": typeof ImplicitValue, + "Comment": typeof Comment, + "CilkFor": typeof CilkFor, + "CilkSync": typeof CilkSync, + "CilkSpawn": typeof CilkSpawn, + "Attribute": typeof Attribute, + "Type": typeof Type, "PointerType": typeof PointerType, - "QualType": typeof QualType, - "ReturnStmt": typeof ReturnStmt, - "Scope": typeof Scope, - "TagType": typeof TagType, - "TemplateSpecializationType": typeof TemplateSpecializationType, - "TypedefDecl": typeof TypedefDecl, - "Vardecl": typeof Vardecl, + "ArrayType": typeof ArrayType, + "AdjustedType": typeof AdjustedType, "VariableArrayType": typeof VariableArrayType, - "Body": typeof Body, - "CilkFor": typeof CilkFor, + "IncompleteArrayType": typeof IncompleteArrayType, + "TagType": typeof TagType, "EnumType": typeof EnumType, - "Param": typeof Param, + "TemplateSpecializationType": typeof TemplateSpecializationType, + "FunctionType": typeof FunctionType, + "QualType": typeof QualType, + "BuiltinType": typeof BuiltinType, + "ParenType": typeof ParenType, + "UndefinedType": typeof UndefinedType, + "ElaboratedType": typeof ElaboratedType, + "TypedefType": typeof TypedefType, }; type DefaultAttributeMap = { + Program: "name", FileJp: "name", - Include: "name", NamedDecl: "name", - Pragma: "name", - Program: "name", + Declarator: "name", + Include: "name", RecordJp: "name", + Field: "name", Struct: "name", - Tag: "id", - TypedefNameDecl: "name", - Varref: "name", - AccessSpecifier: "kind", - Call: "name", - CilkSpawn: "name", Class: "name", - CudaKernelCall: "name", - Declarator: "name", + Vardecl: "name", + TypedefNameDecl: "name", + TypedefDecl: "name", EnumDecl: "name", EnumeratorDecl: "name", - Field: "name", - FunctionJp: "name", LabelDecl: "name", - Loop: "kind", - Marker: "id", - MemberCall: "name", + AccessSpecifier: "kind", + Param: "name", + FunctionJp: "name", Method: "name", + Pragma: "name", + Marker: "id", + Tag: "id", Omp: "kind", - TypedefDecl: "name", - Vardecl: "name", + Loop: "kind", + Call: "name", + MemberCall: "name", + CudaKernelCall: "name", + Varref: "name", CilkFor: "kind", - Param: "name", + CilkSpawn: "name", } export class Joinpoint extends LaraJoinPoint { @@ -145,145 +145,134 @@ export class Joinpoint extends LaraJoinPoint { /** * String with a dump of the AST representation starting from this node. This representation corresponds to the internal Java representation of the ClavaAst, where the node names correspond to Java classes. To get an equivalent representation with join point names, use the attribute 'dump' */ - get ast(): string { return wrapJoinPoint(this._javaObject.getAst()) } + get ast(): string { return wrapJoinPoint(this._javaObject.ast()) } /** * Returns an array with the children of the node, considering null nodes */ - get astChildren(): Joinpoint[] { return wrapJoinPoint(this._javaObject.getAstChildren()) } + get astChildren(): Joinpoint[] { return wrapJoinPoint(this._javaObject.astChildren()) } /** - * String that uniquely identifies this node + * The AST ID of the current node */ - get astId(): string { return wrapJoinPoint(this._javaObject.getAstId()) } + get astId(): string { return wrapJoinPoint(this._javaObject.astId()) } /** * The name of the Java class of this node, which is similar to the equivalent node in Clang AST */ - get astName(): string { return wrapJoinPoint(this._javaObject.getAstName()) } + get astName(): string { return wrapJoinPoint(this._javaObject.astName()) } /** * Returns the number of children of the node, considering null nodes */ - get astNumChildren(): number { return wrapJoinPoint(this._javaObject.getAstNumChildren()) } + get astNumChildren(): number { return wrapJoinPoint(this._javaObject.astNumChildren()) } /** * The bit width of the type returned by this join point, in relation to the definitions of its Translation Unit, or undefined if there is no type or bitwidth defined, or if the join point is not in a TranslationUnit */ - get bitWidth(): number { return wrapJoinPoint(this._javaObject.getBitWidth()) } + get bitWidth(): number { return wrapJoinPoint(this._javaObject.bitWidth()) } /** * String list of the names of the join points that form a path from the root to this node */ - get chain(): string[] { return wrapJoinPoint(this._javaObject.getChain()) } - /** - * Returns an array with the children of the node, ignoring null nodes - */ - get children(): Joinpoint[] { return wrapJoinPoint(this._javaObject.getChildren()) } + get chain(): string[] { return wrapJoinPoint(this._javaObject.chain()) } /** - * String with the code represented by this node + * The children of this join point, ignoring null nodes */ - get code(): string { return wrapJoinPoint(this._javaObject.getCode()) } + get children(): Joinpoint[] { return wrapJoinPoint(this._javaObject.children()) } /** - * The starting column of the current node in the original code + * Returns the current region of this join point */ - get column(): number { return wrapJoinPoint(this._javaObject.getColumn()) } - /** - * Returns the node that declares the scope of this node - */ - get currentRegion(): Joinpoint { return wrapJoinPoint(this._javaObject.getCurrentRegion()) } + get currentRegion(): Joinpoint { return wrapJoinPoint(this._javaObject.currentRegion()) } /** * JS object associated with this node, containing parsed data of #pragma clava data when the node can be a target of pragmas. This is a special object, managed internally, and cannot be reassigned, to change its contents requires using key-value pairs. If the node can be the target of a pragma, the information stored in this object is persisted between rebuilds. */ - get data(): any { const data = (this._javaObject.getData() as string | undefined); return data ? JSON.parse(data) : data; } + get data(): any { const data = (this._javaObject.data() as string | undefined); return data ? JSON.parse(data) : data; } /** * JS object associated with this node, containing parsed data of #pragma clava data when the node can be a target of pragmas. This is a special object, managed internally, and cannot be reassigned, to change its contents requires using key-value pairs. If the node can be the target of a pragma, the information stored in this object is persisted between rebuilds. */ set data(value: object) { this._javaObject.setData(JSON.stringify(value)); } /** - * The depth of this join point in the AST. If it is the root join point returns 0, if it is a child of the root node returns 1, etc. + * Returns the depth of this node in the AST. Root=0 */ - get depth(): number { return wrapJoinPoint(this._javaObject.getDepth()) } + get depth(): number { return wrapJoinPoint(this._javaObject.depth()) } /** - * Retrieves all descendants of the join point + * All descendants of this join point */ - get descendants(): Joinpoint[] { return wrapJoinPoint(this._javaObject.getDescendants()) } + get descendants(): Joinpoint[] { return wrapJoinPoint(this._javaObject.descendants()) } /** * The ending column of the current node in the original code */ - get endColumn(): number { return wrapJoinPoint(this._javaObject.getEndColumn()) } + get endColumn(): number { return wrapJoinPoint(this._javaObject.endColumn()) } /** * The ending line of the current node in the original code */ - get endLine(): number { return wrapJoinPoint(this._javaObject.getEndLine()) } + get endLine(): number { return wrapJoinPoint(this._javaObject.endLine()) } /** - * The name of the file where the code of this node is located, if available + * The filename of the current node */ - get filename(): string { return wrapJoinPoint(this._javaObject.getFilename()) } + get filename(): string { return wrapJoinPoint(this._javaObject.filename()) } /** - * The complete path to the file where the code of this node comes from + * The file path of the current node */ - get filepath(): string { return wrapJoinPoint(this._javaObject.getFilepath()) } + get filepath(): string { return wrapJoinPoint(this._javaObject.filepath()) } /** * Returns the first child of this node, or undefined if it has no child */ - get firstChild(): Joinpoint { return wrapJoinPoint(this._javaObject.getFirstChild()) } + get firstChild(): Joinpoint { return wrapJoinPoint(this._javaObject.firstChild()) } /** * Returns the first child of this node, or undefined if it has no child */ set firstChild(value: Joinpoint) { this._javaObject.setFirstChild(unwrapJoinPoint(value)); } /** - * True if the node has children, false otherwise - */ - get hasChildren(): boolean { return wrapJoinPoint(this._javaObject.getHasChildren()) } - /** - * True if this node has a parent + * True if the node has any children */ - get hasParent(): boolean { return wrapJoinPoint(this._javaObject.getHasParent()) } + get hasChildren(): boolean { return wrapJoinPoint(this._javaObject.hasChildren()) } + get hasParent(): boolean { return wrapJoinPoint(this._javaObject.hasParent()) } /** * True, if the join point has a type */ - get hasType(): boolean { return wrapJoinPoint(this._javaObject.getHasType()) } + get hasType(): boolean { return wrapJoinPoint(this._javaObject.hasType()) } /** * Returns comments that are not explicitly in the AST, but embedded in other nodes */ - get inlineComments(): Comment[] { return wrapJoinPoint(this._javaObject.getInlineComments()) } + get inlineComments(): Comment[] { return wrapJoinPoint(this._javaObject.inlineComments()) } /** * Returns comments that are not explicitly in the AST, but embedded in other nodes */ set inlineComments(value: string[] | string) { this._javaObject.setInlineComments(unwrapJoinPoint(value)); } /** - * True if this is a Cilk node (i.e., cilk_spawn, cilk_sync or cilk_for) + * True if the node is a Cilk node */ - get isCilk(): boolean { return wrapJoinPoint(this._javaObject.getIsCilk()) } + get isCilk(): boolean { return wrapJoinPoint(this._javaObject.isCilk()) } /** - * True, if the join point is part of a system header file + * True, if the join point is inside a header (e.g., function declaration) */ - get isInSystemHeader(): boolean { return wrapJoinPoint(this._javaObject.getIsInSystemHeader()) } + get isInsideHeader(): boolean { return wrapJoinPoint(this._javaObject.isInsideHeader()) } /** - * True, if the join point is inside a header (e.g., if condition, for, while) + * True, if the join point is inside a loop header (e.g., for, while) */ - get isInsideHeader(): boolean { return wrapJoinPoint(this._javaObject.getIsInsideHeader()) } + get isInsideLoopHeader(): boolean { return wrapJoinPoint(this._javaObject.isInsideLoopHeader()) } /** - * True, if the join point is inside a loop header (e.g., for, while) + * True, if the join point is inside a system header (e.g., #include ) */ - get isInsideLoopHeader(): boolean { return wrapJoinPoint(this._javaObject.getIsInsideLoopHeader()) } + get isInSystemHeader(): boolean { return wrapJoinPoint(this._javaObject.isInSystemHeader()) } /** * True if any descendant or the node itself was defined as a macro */ - get isMacro(): boolean { return wrapJoinPoint(this._javaObject.getIsMacro()) } + get isMacro(): boolean { return wrapJoinPoint(this._javaObject.isMacro()) } /** * The names of the Java fields of this node. Can be used as key of the attribute 'javaValue' * * @deprecated used attribute 'keys' instead, together with 'getValue' */ - get javaFields(): string[] { return wrapJoinPoint(this._javaObject.getJavaFields()) } + get javaFields(): string[] { return wrapJoinPoint(this._javaObject.javaFields()) } /** - * Id that is based on the position of the node in the code, and should remain stable between compilations (warning: only a few nodes - file, function, loop - currently support it) + * Returns the ID of this join point. The ID is based on the position of the node in the code, and should remain stable between compilations (warning: only a few nodes - file, function, loop - currently support it) */ - get jpId(): string { return wrapJoinPoint(this._javaObject.getJpId()) } + get jpId(): string { return wrapJoinPoint(this._javaObject.jpId()) } /** * A list of the properties currently supported by this node. Can be used as parameter of the attribute 'getValue' */ - get keys(): string[] { return wrapJoinPoint(this._javaObject.getKeys()) } + get keys(): string[] { return wrapJoinPoint(this._javaObject.keys()) } /** * Returns the last child of this node, or undefined if it has no child */ - get lastChild(): Joinpoint { return wrapJoinPoint(this._javaObject.getLastChild()) } + get lastChild(): Joinpoint { return wrapJoinPoint(this._javaObject.lastChild()) } /** * Returns the last child of this node, or undefined if it has no child */ @@ -291,69 +280,85 @@ export class Joinpoint extends LaraJoinPoint { /** * Returns the node that came before this node, or undefined if there is none */ - get leftJp(): Joinpoint { return wrapJoinPoint(this._javaObject.getLeftJp()) } - /** - * The starting line of the current node in the original code - */ - get line(): number { return wrapJoinPoint(this._javaObject.getLine()) } + get leftJp(): Joinpoint { return wrapJoinPoint(this._javaObject.leftJp()) } /** * A string with information about the file and code position of this node, if available */ - get location(): string { return wrapJoinPoint(this._javaObject.getLocation()) } + get location(): string { return wrapJoinPoint(this._javaObject.location()) } /** * Returns the number of children of the node, ignoring null nodes */ - get numChildren(): number { return wrapJoinPoint(this._javaObject.getNumChildren()) } + get numChildren(): number { return wrapJoinPoint(this._javaObject.numChildren()) } /** * If this join point was not originally from the parsed AST, returns the first join point of the original AST that contributed to its origin */ - get originNode(): Joinpoint { return wrapJoinPoint(this._javaObject.getOriginNode()) } + get originNode(): Joinpoint { return wrapJoinPoint(this._javaObject.originNode()) } /** * Returns the parent node in the AST, or undefined if it is the root node */ - get parent(): Joinpoint { return wrapJoinPoint(this._javaObject.getParent()) } + get parent(): Joinpoint { return wrapJoinPoint(this._javaObject.parent()) } /** - * Returns the node that declares the scope that is a parent of the scope of this node + * Returns the parent region of this join point, or undefined if there is none */ - get parentRegion(): Joinpoint { return wrapJoinPoint(this._javaObject.getParentRegion()) } + get parentRegion(): Joinpoint { return wrapJoinPoint(this._javaObject.parentRegion()) } /** - * The pragmas associated with this node + * Returns the pragmas associated with this join point */ - get pragmas(): Pragma[] { return wrapJoinPoint(this._javaObject.getPragmas()) } + get pragmas(): Pragma[] { return wrapJoinPoint(this._javaObject.pragmas()) } /** * Returns the node that comes after this node, or undefined if there is none */ - get rightJp(): Joinpoint { return wrapJoinPoint(this._javaObject.getRightJp()) } + get rightJp(): Joinpoint { return wrapJoinPoint(this._javaObject.rightJp()) } /** - * Returns the 'program' joinpoint + * Returns the 'program' joinpoint at the root of the hierarchy */ - get root(): Program { return wrapJoinPoint(this._javaObject.getRoot()) } + get root(): Program { return wrapJoinPoint(this._javaObject.root()) } /** - * The nodes of the scope of the current join point. If this node has a body (e.g., loop, function) corresponds to the children of the body. Otherwise, returns an empty array + * The scope nodes of this join point */ - get scopeNodes(): Joinpoint[] { return wrapJoinPoint(this._javaObject.getScopeNodes()) } + get scopeNodes(): Joinpoint[] { return wrapJoinPoint(this._javaObject.scopeNodes()) } /** * Returns an array with the siblings that came before this node */ - get siblingsLeft(): Joinpoint[] { return wrapJoinPoint(this._javaObject.getSiblingsLeft()) } + get siblingsLeft(): Joinpoint[] { return wrapJoinPoint(this._javaObject.siblingsLeft()) } /** * Returns an array with the siblings that come after this node */ - get siblingsRight(): Joinpoint[] { return wrapJoinPoint(this._javaObject.getSiblingsRight()) } + get siblingsRight(): Joinpoint[] { return wrapJoinPoint(this._javaObject.siblingsRight()) } /** * Converts this join point to a statement, or returns undefined if it was not possible */ - get stmt(): Statement { return wrapJoinPoint(this._javaObject.getStmt()) } - get type(): Type { return wrapJoinPoint(this._javaObject.getType()) } + get stmt(): Statement { return wrapJoinPoint(this._javaObject.stmt()) } + get type(): Type { return wrapJoinPoint(this._javaObject.type()) } set type(value: Type) { this._javaObject.setType(unwrapJoinPoint(value)); } /** * True, if this node is a Java instance of the given name, which corresponds to a simple Java class name of an AST node. For an equivalent function for join point names, use 'instanceOf(joinPointName)' */ astIsInstance(className: string): boolean { return wrapJoinPoint(this._javaObject.astIsInstance(unwrapJoinPoint(className))); } /** - * True if the given node is a descendant of this node + * Compares this join point with another join point for identity (i.e., whether they represent the same AST node) + */ + compareNodes(aJoinPoint: Joinpoint): boolean { return wrapJoinPoint(this._javaObject.compareNodes(unwrapJoinPoint(aJoinPoint))); } + /** + * Checks if the joinpoint contains the given joinpoint */ contains(jp: Joinpoint): boolean { return wrapJoinPoint(this._javaObject.contains(unwrapJoinPoint(jp))); } + /** + * Performs a copy of the node and its children, but not of the nodes in its fields + */ + copy(): Joinpoint { return wrapJoinPoint(this._javaObject.copy()); } + /** + * Clears all properties from the .data object + */ + dataClear(): void { return wrapJoinPoint(this._javaObject.dataClear()); } + /** + * Performs a copy of the node and its children, including the nodes in their fields (only the first level of field nodes, this function is not recursive) + */ + deepCopy(): Joinpoint { return wrapJoinPoint(this._javaObject.deepCopy()); } + /** + * Removes the node associated to this joinpoint from the AST + */ + detach(): Joinpoint { return wrapJoinPoint(this._javaObject.detach()); } /** * Looks for an ancestor joinpoint name, walking back on the AST */ @@ -379,11 +384,11 @@ export class Joinpoint extends LaraJoinPoint { */ getDescendants(type: string): Joinpoint[] { return wrapJoinPoint(this._javaObject.getDescendants(unwrapJoinPoint(type))); } /** - * Retrieves the descendants of the given type, including the node itself + * Retrieves the descendants of the given type, including the current joinpoint */ getDescendantsAndSelf(type: string): Joinpoint[] { return wrapJoinPoint(this._javaObject.getDescendantsAndSelf(unwrapJoinPoint(type))); } /** - * Looks in the descendants for the first node of the given type + * Retrieves the first node of the given type in the descendants */ getFirstJp(type: string): Joinpoint { return wrapJoinPoint(this._javaObject.getFirstJp(unwrapJoinPoint(type))); } /** @@ -391,7 +396,7 @@ export class Joinpoint extends LaraJoinPoint { */ getJavaFieldType(fieldName: string): string { return wrapJoinPoint(this._javaObject.getJavaFieldType(unwrapJoinPoint(fieldName))); } /** - * Java Class instance with the type of the given key + * Returns the type of the property with the given name */ getKeyType(key: string): object { return wrapJoinPoint(this._javaObject.getKeyType(unwrapJoinPoint(key))); } /** @@ -399,57 +404,44 @@ export class Joinpoint extends LaraJoinPoint { */ getUserField(fieldName: string): object { return wrapJoinPoint(this._javaObject.getUserField(unwrapJoinPoint(fieldName))); } /** - * The value associated with the given property key + * Returns the value of the property with the given name */ getValue(key: string): object { return wrapJoinPoint(this._javaObject.getValue(unwrapJoinPoint(key))); } /** * True, if the given join point or AST node is the same (== test) as the current join point AST node */ hasNode(nodeOrJp: object): boolean { return wrapJoinPoint(this._javaObject.hasNode(unwrapJoinPoint(nodeOrJp))); } + insert(position: InsertPosition, code: string): Joinpoint[]; + insert(position: InsertPosition, joinpoint: Joinpoint): Joinpoint[]; + insert(p1: InsertPosition, p2: string | Joinpoint): Joinpoint[] { return wrapJoinPoint(this._javaObject.insert(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } /** - * List with the values of fields that are join points, recursively - */ - jpFields(recursive: boolean = false): Joinpoint[] { return wrapJoinPoint(this._javaObject.jpFields(unwrapJoinPoint(recursive))); } - /** - * Performs a copy of the node and its children, but not of the nodes in its fields - */ - copy(): Joinpoint { return wrapJoinPoint(this._javaObject.copy()); } - /** - * Clears all properties from the .data object - */ - dataClear(): void { return wrapJoinPoint(this._javaObject.dataClear()); } - /** - * Performs a copy of the node and its children, including the nodes in their fields (only the first level of field nodes, this function is not recursive) - */ - deepCopy(): Joinpoint { return wrapJoinPoint(this._javaObject.deepCopy()); } - /** - * Removes the node associated to this joinpoint from the AST - */ - detach(): Joinpoint { return wrapJoinPoint(this._javaObject.detach()); } - /** - * Inserts the given join point after this join point + * Inserts the given joinpoint after this joinpoint */ insertAfter(node: Joinpoint): Joinpoint; /** - * Overload which accepts a string + * Overload that accepts a string */ - insertAfter(code: string): Joinpoint; + insertAfter(node: string): Joinpoint; /** - * Inserts the given join point after this join point + * Inserts the given joinpoint after this joinpoint */ insertAfter(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); } /** - * Inserts the given join point before this join point + * Inserts the given joinpoint before this joinpoint */ insertBefore(node: Joinpoint): Joinpoint; /** - * Overload which accepts a string + * Overload that accepts a string */ insertBefore(node: string): Joinpoint; /** - * Inserts the given join point before this join point + * Inserts the given joinpoint before this joinpoint */ insertBefore(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); } + /** + * List with the values of fields that are join points, recursively + */ + jpFields(recursive: boolean = false): Joinpoint[] { return wrapJoinPoint(this._javaObject.jpFields(unwrapJoinPoint(recursive))); } /** * Adds a message that will be printed to the user after weaving finishes. Identical messages are removed */ @@ -463,11 +455,11 @@ export class Joinpoint extends LaraJoinPoint { */ replaceWith(node: Joinpoint): Joinpoint; /** - * Overload which accepts a string + * Overload that accepts a string */ replaceWith(node: string): Joinpoint; /** - * Overload which accepts a list of join points + * Overload that accepts a list of joinpoints */ replaceWith(node: Joinpoint[]): Joinpoint; /** @@ -475,31 +467,35 @@ export class Joinpoint extends LaraJoinPoint { */ replaceWith(p1: Joinpoint | string | Joinpoint[]): Joinpoint { return wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); } /** - * Overload which accepts a list of strings + * Overload that accepts a list of strings */ replaceWithStrings(node: string[]): Joinpoint { return wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); } + /** + * Compares this join point with another join point for identity (i.e., whether they represent the same AST node) + */ + same(other: Joinpoint): boolean { return wrapJoinPoint(this._javaObject.same(unwrapJoinPoint(other))); } /** * Setting data directly is not supported, this action just emits a warning and does nothing */ setData(source: object): void { return wrapJoinPoint(this._javaObject.setData(JSON.stringify(source))); } /** - * Replaces the first child, or inserts the join point if no child is present. Returns the replaced child, or undefined if there was no child present. + * Replaces the first child, or inserts the join point if no child is present. Returns the replaced child, or undefined if there was no child present */ setFirstChild(node: Joinpoint): Joinpoint { return wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); } /** - * Sets the commented that are embedded in a node + * Sets the comments that are embedded in a node */ setInlineComments(comments: string[]): void; /** - * Sets the commented that are embedded in a node + * Sets the comments that are embedded in a node */ setInlineComments(comments: string): void; /** - * Sets the commented that are embedded in a node + * Sets the comments that are embedded in a node */ setInlineComments(p1: string[] | string): void { return wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); } /** - * Replaces the last child, or inserts the join point if no child is present. Returns the replaced child, or undefined if there was no child present. + * Replaces the last child, or inserts the join point if no child is present. Returns the replaced child, or undefined if there was no child present */ setLastChild(node: Joinpoint): Joinpoint { return wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); } /** @@ -511,7 +507,7 @@ export class Joinpoint extends LaraJoinPoint { */ setUserField(fieldName: string, value: object): object; /** - * Overload which accepts a map + * Overload that accepts a map */ setUserField(fieldNameAndValue: Record): object; /** @@ -528,96 +524,126 @@ export class Joinpoint extends LaraJoinPoint { toComment(prefix: string = "", suffix: string = ""): Joinpoint { return wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); } } -export class Attribute extends Joinpoint { + /** + * Utility joinpoint, to represent empty nodes when directly accessing the tree + */ +export class Empty extends Joinpoint { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } } /** - * Utility joinpoint, to represent certain problems when generating join points + * Represents the complete program and is the top-most joinpoint in the hierarchy */ -export class ClavaException extends Joinpoint { +export class Program extends Joinpoint { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; - get exception(): object { return wrapJoinPoint(this._javaObject.getException()) } - get exceptionType(): string { return wrapJoinPoint(this._javaObject.getExceptionType()) } - get message(): string { return wrapJoinPoint(this._javaObject.getMessage()) } -} - -export class Comment extends Joinpoint { + get baseFolder(): string { return wrapJoinPoint(this._javaObject.baseFolder()) } + get defaultFlags(): string[] { return wrapJoinPoint(this._javaObject.defaultFlags()) } /** - * @internal + * Paths to includes that the current program depends on */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get text(): string { return wrapJoinPoint(this._javaObject.getText()) } - set text(value: string) { this._javaObject.setText(unwrapJoinPoint(value)); } - setText(text: string): void { return wrapJoinPoint(this._javaObject.setText(unwrapJoinPoint(text))); } -} - + get extraIncludes(): string[] { return wrapJoinPoint(this._javaObject.extraIncludes()) } /** - * Represents one declaration (e.g., int foo(){return 0;}) or definition (e.g., int foo();) in the code + * Link libraries of external projects the current program depends on */ -export class Decl extends Joinpoint { + get extraLibs(): string[] { return wrapJoinPoint(this._javaObject.extraLibs()) } /** - * @internal + * Paths to folders of projects that the current program depends on */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; + get extraProjects(): string[] { return wrapJoinPoint(this._javaObject.extraProjects()) } /** - * The attributes (e.g. Pure, CUDAGlobal) associated to this decl + * Paths to sources that the current program depends on */ - get attrs(): Attribute[] { return wrapJoinPoint(this._javaObject.getAttrs()) } -} - + get extraSources(): string[] { return wrapJoinPoint(this._javaObject.extraSources()) } /** - * Utility joinpoint, to represent empty nodes when directly accessing the tree + * The files of the program */ -export class Empty extends Joinpoint { + get files(): FileJp[] { return wrapJoinPoint(this._javaObject.files()) } + get includeFolders(): string[] { return wrapJoinPoint(this._javaObject.includeFolders()) } /** - * @internal + * True if the program was compiled with a C++ standard */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; -} - -export class Expression extends Joinpoint { + get isCxx(): boolean { return wrapJoinPoint(this._javaObject.isCxx()) } /** - * @internal + * A function join point with the main function of the program, if one is available */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; + get main(): FunctionJp { return wrapJoinPoint(this._javaObject.main()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } /** - * A 'decl' join point that represents the declaration associated with this expression, or undefined if there is none + * The name of the standard (e.g., c99, c++11) */ - get decl(): Decl { return wrapJoinPoint(this._javaObject.getDecl()) } + get standard(): string { return wrapJoinPoint(this._javaObject.standard()) } /** - * Returns a cast joinpoint if this expression has an associated implicit cast, undefined otherwise + * The flag of the standard (e.g., -std=c++11) */ - get implicitCast(): Cast { return wrapJoinPoint(this._javaObject.getImplicitCast()) } + get stdFlag(): string { return wrapJoinPoint(this._javaObject.stdFlag()) } + get userFlags(): string[] { return wrapJoinPoint(this._javaObject.userFlags()) } + get weavingFolder(): string { return wrapJoinPoint(this._javaObject.weavingFolder()) } /** - * True if the expression is part of an argument of a function call + * Adds a path to an include that the current program depends on + */ + addExtraInclude(path: string): void { return wrapJoinPoint(this._javaObject.addExtraInclude(unwrapJoinPoint(path))); } + /** + * Adds a path based on a git repository to an include that the current program depends on + */ + addExtraIncludeFromGit(gitRepo: string, path?: string): void { return wrapJoinPoint(this._javaObject.addExtraIncludeFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); } + /** + * Adds a library (e.g., -pthreads) that the current program depends on + */ + addExtraLib(lib: string): void { return wrapJoinPoint(this._javaObject.addExtraLib(unwrapJoinPoint(lib))); } + /** + * Adds a path to a source that the current program depends on + */ + addExtraSource(path: string): void { return wrapJoinPoint(this._javaObject.addExtraSource(unwrapJoinPoint(path))); } + /** + * Adds a path based on a git repository to a source that the current program depends on + */ + addExtraSourceFromGit(gitRepo: string, path?: string): void { return wrapJoinPoint(this._javaObject.addExtraSourceFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); } + /** + * Adds a file join point to the current program + */ + addFile(file: FileJp): Joinpoint { return wrapJoinPoint(this._javaObject.addFile(unwrapJoinPoint(file))); } + /** + * Adds a file join point to the current program, from the given path, which can be either a Java File or a String + */ + addFileFromPath(filepath: object): Joinpoint { return wrapJoinPoint(this._javaObject.addFileFromPath(unwrapJoinPoint(filepath))); } + /** + * Adds a path based on a git repository to a project that the current program depends on + */ + addProjectFromGit(gitRepo: string, libs: string[], path?: string): void { return wrapJoinPoint(this._javaObject.addProjectFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(libs), unwrapJoinPoint(path))); } + /** + * Registers a function to be executed when the program exits */ - get isFunctionArgument(): boolean { return wrapJoinPoint(this._javaObject.getIsFunctionArgument()) } - get use(): "read" | "write" | "readwrite" { return wrapJoinPoint(this._javaObject.getUse()) } - get vardecl(): Vardecl { return wrapJoinPoint(this._javaObject.getVardecl()) } + atexit(func: FunctionJp): void { return wrapJoinPoint(this._javaObject.atexit(unwrapJoinPoint(func))); } + /** + * Discards the AST at the top of the AST stack + */ + pop(): void { return wrapJoinPoint(this._javaObject.pop()); } + /** + * Creates a copy of the current AST and pushes it to the top of the AST stack + */ + push(): void { return wrapJoinPoint(this._javaObject.push()); } + /** + * Recompiles the program currently represented by the AST, transforming literal code into AST nodes. Returns true if all files could be parsed correctly, or false otherwise + */ + rebuild(): boolean { return wrapJoinPoint(this._javaObject.rebuild()); } + /** + * Similar to rebuild, but tries to fix compilation errors. Resulting program may not represent the originally intended functionality + */ + rebuildFuzzy(): void { return wrapJoinPoint(this._javaObject.rebuildFuzzy()); } } /** - * Represents a source file (.c, .cpp., .cl, etc) + * Represents a source file (.c, .cpp, .cl, etc) */ export class FileJp extends Joinpoint { /** @@ -627,73 +653,63 @@ export class FileJp extends Joinpoint { name: "name", }; /** - * The path to the source folder that was given as the base folder of this file + * The base source path for this file */ - get baseSourcePath(): string { return wrapJoinPoint(this._javaObject.getBaseSourcePath()) } + get baseSourcePath(): string { return wrapJoinPoint(this._javaObject.baseSourcePath()) } /** - * The output of the parser if there were errors during parsing + * The error output produced during the parsing of this file, if any */ - get errorOutput(): string { return wrapJoinPoint(this._javaObject.getErrorOutput()) } + get errorOutput(): string { return wrapJoinPoint(this._javaObject.errorOutput()) } /** - * A Java file to the file that originated this translation unit + * The Java File object associated with this file */ - get file(): object { return wrapJoinPoint(this._javaObject.getFile()) } + get file(): object { return wrapJoinPoint(this._javaObject.file()) } /** - * True if this file contains a 'main' method + * True if this file has the main function as a descendant */ - get hasMain(): boolean { return wrapJoinPoint(this._javaObject.getHasMain()) } + get hasMain(): boolean { return wrapJoinPoint(this._javaObject.hasMain()) } /** - * True if there were errors during parsing + * True if there were errors during the parsing of this file */ - get hasParsingErrors(): boolean { return wrapJoinPoint(this._javaObject.getHasParsingErrors()) } + get hasParsingErrors(): boolean { return wrapJoinPoint(this._javaObject.hasParsingErrors()) } /** - * The includes of this file + * The include directives in this file */ - get includes(): Include[] { return wrapJoinPoint(this._javaObject.getIncludes()) } + get includes(): Include[] { return wrapJoinPoint(this._javaObject.includes()) } /** - * True if this file is considered a C++ file + * True if this file is a being parsed as a C++ file */ - get isCxx(): boolean { return wrapJoinPoint(this._javaObject.getIsCxx()) } + get isCxx(): boolean { return wrapJoinPoint(this._javaObject.isCxx()) } /** - * True if this file is considered a header file + * True if this file is a header file */ - get isHeader(): boolean { return wrapJoinPoint(this._javaObject.getIsHeader()) } + get isHeader(): boolean { return wrapJoinPoint(this._javaObject.isHeader()) } /** - * True if this file is an OpenCL filetype - */ - get isOpenCL(): boolean { return wrapJoinPoint(this._javaObject.getIsOpenCL()) } - /** - * The name of the file - */ - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } - /** - * The name of the file + * True if this file is an OpenCL file */ + get isOpenCL(): boolean { return wrapJoinPoint(this._javaObject.isOpenCL()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } /** - * The folder of the source file + * The folder path for this file */ - get path(): string { return wrapJoinPoint(this._javaObject.getPath()) } + get path(): string { return wrapJoinPoint(this._javaObject.path()) } /** - * The path to the file relative to the base source path + * The file path relative to the base folder of the program */ - get relativeFilepath(): string { return wrapJoinPoint(this._javaObject.getRelativeFilepath()) } + get relativeFilepath(): string { return wrapJoinPoint(this._javaObject.relativeFilepath()) } /** - * The path to the folder of the source file relative to the base source path + * The folder path relative to the base folder of the program */ - get relativeFolderpath(): string { return wrapJoinPoint(this._javaObject.getRelativeFolderpath()) } + get relativeFolderpath(): string { return wrapJoinPoint(this._javaObject.relativeFolderpath()) } /** - * The path to the folder of the source file relative to the base source path + * The folder path relative to the base folder of the program */ set relativeFolderpath(value: string) { this._javaObject.setRelativeFolderpath(unwrapJoinPoint(value)); } /** * The name of the source folder of this file, or undefined if it has none */ - get sourceFoldername(): string { return wrapJoinPoint(this._javaObject.getSourceFoldername()) } - /** - * The complete path to the file that will be generated by the weaver, given a destination folder - */ - getDestinationFilepath(destinationFolderpath?: string): string { return wrapJoinPoint(this._javaObject.getDestinationFilepath(unwrapJoinPoint(destinationFolderpath))); } + get sourceFoldername(): string { return wrapJoinPoint(this._javaObject.sourceFoldername()) } /** * Adds a C include to the current file. If the file already has the include, it does nothing */ @@ -714,6 +730,10 @@ export class FileJp extends Joinpoint { * Overload of addInclude which accepts a join point */ addIncludeJp(jp: Joinpoint): void { return wrapJoinPoint(this._javaObject.addIncludeJp(unwrapJoinPoint(jp))); } + /** + * The complete path to the file that will be generated by the weaver, given a destination folder + */ + getDestinationFilepath(destinationFolderpath?: string): string { return wrapJoinPoint(this._javaObject.getDestinationFilepath(unwrapJoinPoint(destinationFolderpath))); } /** * Adds the node in the join point to the start of the file */ @@ -742,10 +762,6 @@ export class FileJp extends Joinpoint { * Recompiles only this file, returns a join point to the new recompiled file, or throws an exception if a problem happens */ rebuild(): FileJp { return wrapJoinPoint(this._javaObject.rebuild()); } - /** - * Recompiles only this file, returns a join point to the new recompiled file, or returns a clavaException join point if a problem happens - */ - rebuildTry(): Joinpoint { return wrapJoinPoint(this._javaObject.rebuildTry()); } /** * Changes the name of the file */ @@ -760,340 +776,347 @@ export class FileJp extends Joinpoint { write(destinationFoldername: string): string { return wrapJoinPoint(this._javaObject.write(unwrapJoinPoint(destinationFoldername))); } } -export class ImplicitValue extends Expression { + /** + * Represents one declaration (e.g., int foo(){return 0;}) or definition (e.g., int foo();) + */ +export class Decl extends Joinpoint { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; + /** + * The attributes of this declaration (e.g. Pure, CUDAGlobal), if any + */ + get attrs(): Attribute[] { return wrapJoinPoint(this._javaObject.attrs()) } } /** - * Represents an include directive (e.g., #include ) + * Represents a decl with a name */ -export class Include extends Decl { +export class NamedDecl extends Decl { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; + get isPublic(): boolean { return wrapJoinPoint(this._javaObject.isPublic()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } + set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } + get qualifiedName(): string { return wrapJoinPoint(this._javaObject.qualifiedName()) } + set qualifiedName(value: string) { this._javaObject.setQualifiedName(unwrapJoinPoint(value)); } + get qualifiedPrefix(): string { return wrapJoinPoint(this._javaObject.qualifiedPrefix()) } + set qualifiedPrefix(value: string) { this._javaObject.setQualifiedPrefix(unwrapJoinPoint(value)); } /** - * True if this is an angled include (i.e., system include) + * Sets the name of this namedDecl */ - get isAngled(): boolean { return wrapJoinPoint(this._javaObject.getIsAngled()) } + setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } /** - * The name of the include + * Sets the qualified name of this namedDecl (changes both the name and qualified prefix) */ - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } + setQualifiedName(name: string): void { return wrapJoinPoint(this._javaObject.setQualifiedName(unwrapJoinPoint(name))); } /** - * The path to the folder of the source file of the include, relative to the name of the include + * Sets the qualified prefix of this namedDecl */ - get relativeFolderpath(): string { return wrapJoinPoint(this._javaObject.getRelativeFolderpath()) } + setQualifiedPrefix(qualifiedPrefix: string): void { return wrapJoinPoint(this._javaObject.setQualifiedPrefix(unwrapJoinPoint(qualifiedPrefix))); } } -export class InitList extends Expression { - /** - * @internal - */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; /** - * [May be undefined] If this initializer list initializes an array with more elements than there are initializers in the list, specifies an expression to be used for value initialization of the rest of the elements + * Represents a decl that comes from a declarator (e.g., function, field, variable) */ - get arrayFiller(): Expression { return wrapJoinPoint(this._javaObject.getArrayFiller()) } -} - -export class Literal extends Expression { +export class Declarator extends NamedDecl { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; } -export class MemberAccess extends Expression { + /** + * Represents an include directive (e.g., #include ) + */ +export class Include extends Decl { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; /** - * True if this is a member access that uses arrow (i.e., foo->bar), false if uses dot (i.e., foo.bar) - */ - get arrow(): boolean { return wrapJoinPoint(this._javaObject.getArrow()) } - /** - * True if this is a member access that uses arrow (i.e., foo->bar), false if uses dot (i.e., foo.bar) + * True if the include is angled (e.g., #include ) instead of quoted (e.g., #include "myheader.h") */ - set arrow(value: boolean) { this._javaObject.setArrow(unwrapJoinPoint(value)); } + get isAngled(): boolean { return wrapJoinPoint(this._javaObject.isAngled()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } /** - * Expression of the base of this member access + * The path to the folder of the source file of the include, relative to the name of the include */ - get base(): Expression { return wrapJoinPoint(this._javaObject.getBase()) } - get memberChain(): Expression[] { return wrapJoinPoint(this._javaObject.getMemberChain()) } - get memberChainNames(): string[] { return wrapJoinPoint(this._javaObject.getMemberChainNames()) } - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } - setArrow(isArrow: boolean): void { return wrapJoinPoint(this._javaObject.setArrow(unwrapJoinPoint(isArrow))); } + get relativeFolderpath(): string { return wrapJoinPoint(this._javaObject.relativeFolderpath()) } } /** - * Represents a decl with a name + * Represents a record declaration (struct, union, or class) */ -export class NamedDecl extends Decl { +export class RecordJp extends NamedDecl { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; - get isPublic(): boolean { return wrapJoinPoint(this._javaObject.getIsPublic()) } - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } - set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } - get qualifiedName(): string { return wrapJoinPoint(this._javaObject.getQualifiedName()) } - set qualifiedName(value: string) { this._javaObject.setQualifiedName(unwrapJoinPoint(value)); } - get qualifiedPrefix(): string { return wrapJoinPoint(this._javaObject.getQualifiedPrefix()) } - set qualifiedPrefix(value: string) { this._javaObject.setQualifiedPrefix(unwrapJoinPoint(value)); } + get fields(): Field[] { return wrapJoinPoint(this._javaObject.fields()) } + get functions(): FunctionJp[] { return wrapJoinPoint(this._javaObject.functions()) } /** - * Sets the name of this namedDecl + * True if this record declaration is an implementation (i.e., it has a body) instead of just a forward declaration */ - setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } + get isImplementation(): boolean { return wrapJoinPoint(this._javaObject.isImplementation()) } /** - * Sets the qualified name of this namedDecl (changes both the name and qualified prefix) + * True if this record declaration is a prototype (i.e., it has no body) instead of an implementation */ - setQualifiedName(name: string): void { return wrapJoinPoint(this._javaObject.setQualifiedName(unwrapJoinPoint(name))); } + get isPrototype(): boolean { return wrapJoinPoint(this._javaObject.isPrototype()) } + get kind(): string { return wrapJoinPoint(this._javaObject.kind()) } /** - * Sets the qualified prefix of this namedDecl + * Adds a field to a record (struct, class) */ - setQualifiedPrefix(qualifiedPrefix: string): void { return wrapJoinPoint(this._javaObject.setQualifiedPrefix(unwrapJoinPoint(qualifiedPrefix))); } + addField(field: Field): void { return wrapJoinPoint(this._javaObject.addField(unwrapJoinPoint(field))); } } -export class NewExpr extends Expression { + /** + * Represents a member of a struct/union/class + */ +export class Field extends Declarator { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; } -export class Op extends Expression { + /** + * Represents a struct declaration + */ +export class Struct extends RecordJp { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; - get isBitwise(): boolean { return wrapJoinPoint(this._javaObject.getIsBitwise()) } - /** - * The kind of the operator. If it is a binary operator, can be one of: ptr_mem_d, ptr_mem_i, mul, div, rem, add, sub, shl, shr, cmp, lt, gt, le, ge, eq, ne, and, xor, or, l_and, l_or, assign, mul_assign, div_assign, rem_assign, add_assign, sub_assign, shl_assign, shr_assign, and_assign, xor_assign, or_assign, comma. If it is a unary operator, can be one of: post_inc, post_dec, pre_inc, pre_dec, addr_of, deref, plus, minus, not, l_not, real, imag, extension, cowait. If it is a ternary operator, the value will be 'ternary' - */ - get kind(): "ptr_mem_d" | "ptr_mem_i" | "mul" | "div" | "rem" | "add" | "sub" | "shl" | "shr" | "cmp" | "lt" | "gt" | "le" | "ge" | "eq" | "ne" | "and" | "xor" | "or" | "l_and" | "l_or" | "assign" | "mul_assign" | "div_assign" | "rem_assign" | "add_assign" | "sub_assign" | "shl_assign" | "shr_assign" | "and_assign" | "xor_assign" | "or_assign" | "comma" | "post_inc" | "post_dec" | "pre_inc" | "pre_dec" | "addr_of" | "deref" | "plus" | "minus" | "not" | "l_not" | "real" | "imag" | "extension" | "cowait" | "ternary" { return wrapJoinPoint(this._javaObject.getKind()) } - get operator(): string { return wrapJoinPoint(this._javaObject.getOperator()) } } -export class ParenExpr extends Expression { + /** + * Represents a C++ class declaration + */ +export class Class extends RecordJp { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; /** - * Returns the expression inside this parenthesis expression + * The base classes of this class and its base classes */ - get subExpr(): Expression { return wrapJoinPoint(this._javaObject.getSubExpr()) } -} - + get allBases(): Class[] { return wrapJoinPoint(this._javaObject.allBases()) } /** - * Represents a pragma in the code (e.g., #pragma kernel) + * The methods of this class and its base classes */ -export class Pragma extends Joinpoint { + get allMethods(): Method[] { return wrapJoinPoint(this._javaObject.allMethods()) } /** - * @internal + * The base classes of this class */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; + get bases(): Class[] { return wrapJoinPoint(this._javaObject.bases()) } /** - * Everything that is after the name of the pragma + * Class join points can either represent declarations or definitions, returns the definition of this class, if present, or the first declaration, if only declarations are present */ - get content(): string { return wrapJoinPoint(this._javaObject.getContent()) } + get canonical(): Class { return wrapJoinPoint(this._javaObject.canonical()) } /** - * Everything that is after the name of the pragma + * The implementation (or definition) of this class present in the AST, or undefined if none is found */ - set content(value: string) { this._javaObject.setContent(unwrapJoinPoint(value)); } + get implementation(): Class { return wrapJoinPoint(this._javaObject.implementation()) } /** - * The name of the pragma. E.g. for #pragma foo bar, returns 'foo' + * True if this class contains at least one pure function */ - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } + get isAbstract(): boolean { return wrapJoinPoint(this._javaObject.isAbstract()) } /** - * The name of the pragma. E.g. for #pragma foo bar, returns 'foo' + * True if this class join point is the canonical one, which is the definition if it is present, or the first declaration if only declarations are present */ - set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } + get isCanonical(): boolean { return wrapJoinPoint(this._javaObject.isCanonical()) } /** - * The first node below the pragma that is not a comment or another pragma. Example of pragma targets are statements and declarations + * True if this class contains only pure functions */ - get target(): Joinpoint { return wrapJoinPoint(this._javaObject.getTarget()) } + get isInterface(): boolean { return wrapJoinPoint(this._javaObject.isInterface()) } /** - * All the nodes below the target node, including the target node, up until a pragma with the name given by argument 'endPragma'. If no end pragma is found, returns the same result as if not providing the argument + * The methods of this class */ - getTargetNodes(endPragma?: string): Joinpoint[] { return wrapJoinPoint(this._javaObject.getTargetNodes(unwrapJoinPoint(endPragma))); } - setContent(content: string): void { return wrapJoinPoint(this._javaObject.setContent(unwrapJoinPoint(content))); } - setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } + get methods(): Method[] { return wrapJoinPoint(this._javaObject.methods()) } + /** + * The prototypes (or declarations) of this class present in the AST, if any + */ + get prototypes(): Class[] { return wrapJoinPoint(this._javaObject.prototypes()) } + /** + * Adds a method to a class. If the given method has a definition, creates an equivalent declaration and adds it to the class, otherwise simply adds the declaration to the class. In both cases, the declaration is only added to the class if there is no declaration already with the same signature + */ + addMethod(method: Method): void { return wrapJoinPoint(this._javaObject.addMethod(unwrapJoinPoint(method))); } } /** - * Represents the complete program and is the top-most joinpoint in the hierarchy + * Represents a variable declaration or definition */ -export class Program extends Joinpoint { +export class Vardecl extends Declarator { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; - get baseFolder(): string { return wrapJoinPoint(this._javaObject.getBaseFolder()) } - get defaultFlags(): string[] { return wrapJoinPoint(this._javaObject.getDefaultFlags()) } - /** - * Paths to includes that the current program depends on - */ - get extraIncludes(): string[] { return wrapJoinPoint(this._javaObject.getExtraIncludes()) } /** - * Link libraries of external projects the current program depends on + * The vardecl corresponding to the actual definition. For global variables, returns the vardecl of the file where it is actually defined (instead of the vardecl that defines an external link to the variable) */ - get extraLibs(): string[] { return wrapJoinPoint(this._javaObject.getExtraLibs()) } + get definition(): Vardecl { return wrapJoinPoint(this._javaObject.definition()) } /** - * Paths to folders of projects that the current program depends on + * True if this variable declaration has an initializer */ - get extraProjects(): string[] { return wrapJoinPoint(this._javaObject.getExtraProjects()) } + get hasInit(): boolean { return wrapJoinPoint(this._javaObject.hasInit()) } /** - * Paths to sources that the current program depends on + * The initializer of this variable declaration, if it has one */ - get extraSources(): string[] { return wrapJoinPoint(this._javaObject.getExtraSources()) } + get init(): Expression { return wrapJoinPoint(this._javaObject.init()) } /** - * The source files in this program + * The initializer of this variable declaration, if it has one */ - get files(): FileJp[] { return wrapJoinPoint(this._javaObject.getFiles()) } - get includeFolders(): string[] { return wrapJoinPoint(this._javaObject.getIncludeFolders()) } + set init(value: Expression | string) { this._javaObject.setInit(unwrapJoinPoint(value)); } /** - * True if the program was compiled with a C++ standard + * The initialization style of this vardecl, which can be no_init, cinit, callinit, listinit */ - get isCxx(): boolean { return wrapJoinPoint(this._javaObject.getIsCxx()) } + get initStyle(): string { return wrapJoinPoint(this._javaObject.initStyle()) } /** - * A function join point with the main function of the program, if one is available + * True if this variable declaration is global. This includes all global variables as well as static variables declared within a function. */ - get main(): FunctionJp { return wrapJoinPoint(this._javaObject.getMain()) } - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } + get isGlobal(): boolean { return wrapJoinPoint(this._javaObject.isGlobal()) } /** - * The name of the standard (e.g., c99, c++11) + * True if this variable declaration is a function parameter */ - get standard(): string { return wrapJoinPoint(this._javaObject.getStandard()) } + get isParam(): boolean { return wrapJoinPoint(this._javaObject.isParam()) } /** - * The flag of the standard (e.g., -std=c++11) + * The storage class of this variable declaration. Can be 'none', 'extern', 'static', '__private_extern__', 'auto' or 'register' */ - get stdFlag(): string { return wrapJoinPoint(this._javaObject.getStdFlag()) } - get userFlags(): string[] { return wrapJoinPoint(this._javaObject.getUserFlags()) } - get weavingFolder(): string { return wrapJoinPoint(this._javaObject.getWeavingFolder()) } + get storageClass(): StorageClass { return wrapJoinPoint(this._javaObject.storageClass()) } /** - * Adds a path to an include that the current program depends on + * The storage class of this variable declaration. Can be 'none', 'extern', 'static', '__private_extern__', 'auto' or 'register' */ - addExtraInclude(path: string): void { return wrapJoinPoint(this._javaObject.addExtraInclude(unwrapJoinPoint(path))); } + set storageClass(value: StorageClass) { this._javaObject.setStorageClass(unwrapJoinPoint(value)); } /** - * Adds a path based on a git repository to an include that the current program depends on + * If vardecl already has an initialization, removes it */ - addExtraIncludeFromGit(gitRepo: string, path?: string): void { return wrapJoinPoint(this._javaObject.addExtraIncludeFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); } + removeInit(removeConst: boolean = true): void { return wrapJoinPoint(this._javaObject.removeInit(unwrapJoinPoint(removeConst))); } /** - * Adds a library (e.g., -pthreads) that the current program depends on + * Sets the given expression as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization */ - addExtraLib(lib: string): void { return wrapJoinPoint(this._javaObject.addExtraLib(unwrapJoinPoint(lib))); } + setInit(init: Expression): void; /** - * Adds a path to a source that the current program depends on + * Converts the given string to a literal expression and sets it as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization */ - addExtraSource(path: string): void { return wrapJoinPoint(this._javaObject.addExtraSource(unwrapJoinPoint(path))); } + setInit(init: string): void; /** - * Adds a path based on a git repository to a source that the current program depends on + * Sets the given expression as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization */ - addExtraSourceFromGit(gitRepo: string, path?: string): void { return wrapJoinPoint(this._javaObject.addExtraSourceFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); } + setInit(p1: Expression | string): void { return wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(p1))); } /** - * Adds a file join point to the current program + * Sets the storage class specifier, which can be none, extern, static, __private_extern__, auto */ - addFile(file: FileJp): Joinpoint { return wrapJoinPoint(this._javaObject.addFile(unwrapJoinPoint(file))); } + setStorageClass(storageClass: StorageClass): void { return wrapJoinPoint(this._javaObject.setStorageClass(unwrapJoinPoint(storageClass))); } /** - * Adds a file join point to the current program, from the given path, which can be either a Java File or a String + * Creates a new varref based on this vardecl */ - addFileFromPath(filepath: object): Joinpoint { return wrapJoinPoint(this._javaObject.addFileFromPath(unwrapJoinPoint(filepath))); } + varref(): Varref { return wrapJoinPoint(this._javaObject.varref()); } +} + /** - * Adds a path based on a git repository to a project that the current program depends on + * Base node for declarations which introduce a typedef-name */ - addProjectFromGit(gitRepo: string, libs: string[], path?: string): void { return wrapJoinPoint(this._javaObject.addProjectFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(libs), unwrapJoinPoint(path))); } +export class TypedefNameDecl extends NamedDecl { /** - * Registers a function to be executed when the program exits + * @internal */ - atexit(func: FunctionJp): void { return wrapJoinPoint(this._javaObject.atexit(unwrapJoinPoint(func))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; +} + /** - * Discards the AST at the top of the ASt stack + * Declaration of a typedef-name via the 'typedef' type specifier */ - pop(): void { return wrapJoinPoint(this._javaObject.pop()); } +export class TypedefDecl extends TypedefNameDecl { /** - * Creates a copy of the current AST and pushes it to the top of the AST stack + * @internal */ - push(): void { return wrapJoinPoint(this._javaObject.push()); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; +} + /** - * Recompiles the program currently represented by the AST, transforming literal code into AST nodes. Returns true if all files could be parsed correctly, or false otherwise + * Represents an enum declaration */ - rebuild(): boolean { return wrapJoinPoint(this._javaObject.rebuild()); } +export class EnumDecl extends NamedDecl { /** - * Similar to rebuild, but tries to fix compilation errors. Resulting program may not represent the originally intended functionality + * @internal */ - rebuildFuzzy(): void { return wrapJoinPoint(this._javaObject.rebuildFuzzy()); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; + get enumerators(): EnumeratorDecl[] { return wrapJoinPoint(this._javaObject.enumerators()) } } /** - * Common class of struct, union and class + * Represents an enumerator in an enum */ -export class RecordJp extends NamedDecl { +export class EnumeratorDecl extends NamedDecl { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; - get fields(): Field[] { return wrapJoinPoint(this._javaObject.getFields()) } - get functions(): FunctionJp[] { return wrapJoinPoint(this._javaObject.getFunctions()) } - /** - * True if this particular join point is an implementation (i.e. has its body fully specified), false otherwise - */ - get isImplementation(): boolean { return wrapJoinPoint(this._javaObject.getIsImplementation()) } +} + /** - * True if this particular join point is a prototype (i.e. does not have its body fully specified), false otherwise + * Represents a label declaration */ - get isPrototype(): boolean { return wrapJoinPoint(this._javaObject.getIsPrototype()) } - get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } +export class LabelDecl extends NamedDecl { /** - * Adds a field to a record (struct, class). + * @internal */ - addField(field: Field): void { return wrapJoinPoint(this._javaObject.addField(unwrapJoinPoint(field))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; + get labelStmt(): LabelStmt { return wrapJoinPoint(this._javaObject.labelStmt()) } } -export class Statement extends Joinpoint { + /** + * Represents an access specifier (public:, private:, or protected:) in a class declaration + */ +export class AccessSpecifier extends Decl { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "kind", }; - get isFirst(): boolean { return wrapJoinPoint(this._javaObject.getIsFirst()) } - get isLast(): boolean { return wrapJoinPoint(this._javaObject.getIsLast()) } + /** + * The type of specifier. Can return 'public', 'protected', 'private' or 'none' + */ + get kind(): string { return wrapJoinPoint(this._javaObject.kind()) } } /** - * Represets a struct declaration + * Represents a function parameter */ -export class Struct extends RecordJp { +export class Param extends Vardecl { /** * @internal */ @@ -1102,643 +1125,490 @@ export class Struct extends RecordJp { }; } -export class Switch extends Statement { + /** + * Represents a function declaration or definition + */ +export class FunctionJp extends Declarator { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; + get body(): Scope { return wrapJoinPoint(this._javaObject.body()) } + set body(value: Scope) { this._javaObject.setBody(unwrapJoinPoint(value)); } + get calls(): Call[] { return wrapJoinPoint(this._javaObject.calls()) } /** - * The case statements inside this switch + * Function join points can either represent declarations or definitions, returns the definition of this function, if present, or the first declaration, if only declarations are present */ - get cases(): Case[] { return wrapJoinPoint(this._javaObject.getCases()) } + get canonical(): FunctionJp { return wrapJoinPoint(this._javaObject.canonical()) } /** - * The condition of this switch statement + * Returns the first prototype of this function that could be found, or undefined if there is none */ - get condition(): Expression { return wrapJoinPoint(this._javaObject.getCondition()) } + get declarationJp(): FunctionJp { return wrapJoinPoint(this._javaObject.declarationJp()) } /** - * The default case statement of this switch statement or undefined if it does not have a default case + * Returns the prototypes of this function that are present in the code. If there are none, returns an empty array */ - get getDefaultCase(): Case { return wrapJoinPoint(this._javaObject.getGetDefaultCase()) } + get declarationJps(): FunctionJp[] { return wrapJoinPoint(this._javaObject.declarationJps()) } /** - * True if there is a default case in this switch statement, false otherwise + * Returns the implementation of this function if there is one, or undefined otherwise */ - get hasDefaultCase(): boolean { return wrapJoinPoint(this._javaObject.getHasDefaultCase()) } -} - -export class SwitchCase extends Statement { + get definitionJp(): FunctionJp { return wrapJoinPoint(this._javaObject.definitionJp()) } /** - * @internal + * The function type of this function, which includes the return type and the parameter types */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; -} - + get functionType(): FunctionType { return wrapJoinPoint(this._javaObject.functionType()) } /** - * A pragma that references a point in the code and sticks to it + * The function type of this function, which includes the return type and the parameter types */ -export class Tag extends Pragma { + set functionType(value: FunctionType) { this._javaObject.setFunctionType(unwrapJoinPoint(value)); } /** - * @internal + * True if this particular function join point has a body, false otherwise + * + * @deprecated Use .isImplementation instead */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "id", - }; + get hasDefinition(): boolean { return wrapJoinPoint(this._javaObject.hasDefinition()) } + get id(): string { return wrapJoinPoint(this._javaObject.id()) } /** - * The ID of the pragma + * True, if this is the function returned by the 'canonical' attribute */ - get id(): string { return wrapJoinPoint(this._javaObject.getId()) } -} - -export class TernaryOp extends Op { + get isCanonical(): boolean { return wrapJoinPoint(this._javaObject.isCanonical()) } + get isCudaKernel(): boolean { return wrapJoinPoint(this._javaObject.isCudaKernel()) } + get isDelete(): boolean { return wrapJoinPoint(this._javaObject.isDelete()) } /** - * @internal + * True if this function join point is an implementation, false otherwise */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get cond(): Expression { return wrapJoinPoint(this._javaObject.getCond()) } - get falseExpr(): Expression { return wrapJoinPoint(this._javaObject.getFalseExpr()) } - get trueExpr(): Expression { return wrapJoinPoint(this._javaObject.getTrueExpr()) } -} - -export class This extends Expression { + get isImplementation(): boolean { return wrapJoinPoint(this._javaObject.isImplementation()) } + get isInline(): boolean { return wrapJoinPoint(this._javaObject.isInline()) } + get isModulePrivate(): boolean { return wrapJoinPoint(this._javaObject.isModulePrivate()) } /** - * @internal + * True if this function join point is a prototype, false otherwise */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; -} - -export class Type extends Joinpoint { + get isPrototype(): boolean { return wrapJoinPoint(this._javaObject.isPrototype()) } + get isPure(): boolean { return wrapJoinPoint(this._javaObject.isPure()) } + get isVirtual(): boolean { return wrapJoinPoint(this._javaObject.isVirtual()) } + get paramNames(): string[] { return wrapJoinPoint(this._javaObject.paramNames()) } + get params(): Param[] { return wrapJoinPoint(this._javaObject.params()) } + set params(value: Param[]) { this._javaObject.setParams(unwrapJoinPoint(value)); } + get returnType(): Type { return wrapJoinPoint(this._javaObject.returnType()) } + set returnType(value: Type) { this._javaObject.setReturnType(unwrapJoinPoint(value)); } /** - * @internal + * The signature of this function (e.g., name of the function, plus the parameters types) */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get arrayDims(): number[] { return wrapJoinPoint(this._javaObject.getArrayDims()) } - get arraySize(): number { return wrapJoinPoint(this._javaObject.getArraySize()) } - get constant(): boolean { return wrapJoinPoint(this._javaObject.getConstant()) } + get signature(): string { return wrapJoinPoint(this._javaObject.signature()) } + get storageClass(): StorageClass { return wrapJoinPoint(this._javaObject.storageClass()) } + set storageClass(value: StorageClass) { this._javaObject.setStorageClass(unwrapJoinPoint(value)); } /** - * Single-step desugar. Returns the type itself if it does not have sugar + * Adds a new parameter to the function */ - get desugar(): Type { return wrapJoinPoint(this._javaObject.getDesugar()) } + addParam(param: Param): void; /** - * Single-step desugar. Returns the type itself if it does not have sugar + * Adds a new parameter to the function */ - set desugar(value: Type) { this._javaObject.setDesugar(unwrapJoinPoint(value)); } + addParam(name: string, type?: Type): void; /** - * Completely desugars the type + * Adds a new parameter to the function */ - get desugarAll(): Type { return wrapJoinPoint(this._javaObject.getDesugarAll()) } + addParam(p1: Param | string, p2?: Type): void { return wrapJoinPoint(this._javaObject.addParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } /** - * A tree representation of the fields of this type + * Clones this function assigning it a new name, inserts the cloned function after the original function. If the name is the same and the original method, automatically removes the cloned method from the class */ - get fieldTree(): string { return wrapJoinPoint(this._javaObject.getFieldTree()) } - get hasSugar(): boolean { return wrapJoinPoint(this._javaObject.getHasSugar()) } - get hasTemplateArgs(): boolean { return wrapJoinPoint(this._javaObject.getHasTemplateArgs()) } - get isArray(): boolean { return wrapJoinPoint(this._javaObject.getIsArray()) } + clone(newName: string, insert: boolean = true): FunctionJp { return wrapJoinPoint(this._javaObject.clone(unwrapJoinPoint(newName), unwrapJoinPoint(insert))); } /** - * True if this is a type declared with the 'auto' keyword + * Generates a clone of the provided function on a new file with the provided name (or with a weaver-generated name if one is not provided) */ - get isAuto(): boolean { return wrapJoinPoint(this._javaObject.getIsAuto()) } - get isBuiltin(): boolean { return wrapJoinPoint(this._javaObject.getIsBuiltin()) } - get isPointer(): boolean { return wrapJoinPoint(this._javaObject.getIsPointer()) } - get isTopLevel(): boolean { return wrapJoinPoint(this._javaObject.getIsTopLevel()) } - get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } + cloneOnFile(newName: string, fileName?: string): FunctionJp; /** - * Ignores certain types (e.g., DecayedType) + * Generates a clone of the provided function on a new file (with the provided join point) */ - get normalize(): Type { return wrapJoinPoint(this._javaObject.getNormalize()) } - get templateArgsStrings(): string[] { return wrapJoinPoint(this._javaObject.getTemplateArgsStrings()) } - get templateArgsTypes(): Type[] { return wrapJoinPoint(this._javaObject.getTemplateArgsTypes()) } - set templateArgsTypes(value: Type[]) { this._javaObject.setTemplateArgsTypes(unwrapJoinPoint(value)); } + cloneOnFile(newName: string, file: FileJp): FunctionJp; /** - * Maps names of join point fields that represent type join points, to their respective values + * Generates a clone of the provided function on a new file with the provided name (or with a weaver-generated name if one is not provided) */ - get typeFields(): Record { return wrapJoinPoint(this._javaObject.getTypeFields()) } + cloneOnFile(p1: string, p2?: string | FileJp): FunctionJp { return wrapJoinPoint(this._javaObject.cloneOnFile(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + getDeclaration(withReturnType: boolean): string { return wrapJoinPoint(this._javaObject.getDeclaration(unwrapJoinPoint(withReturnType))); } /** - * If the type encapsulates another type, returns the encapsulated type + * Inserts the joinpoint before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node */ - get unwrap(): Type { return wrapJoinPoint(this._javaObject.getUnwrap()) } + insertReturn(code: Joinpoint): Joinpoint; /** - * Returns a new node based on this type with the qualifier const + * Inserts code as a literal statement before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node */ - asConst(): Type { return wrapJoinPoint(this._javaObject.asConst()); } + insertReturn(code: string): Joinpoint; /** - * Sets the desugared type of this type + * Inserts the joinpoint before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node */ - setDesugar(desugaredType: Type): void { return wrapJoinPoint(this._javaObject.setDesugar(unwrapJoinPoint(desugaredType))); } + insertReturn(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); } /** - * Sets a single template argument type of a template type + * Creates a new call to this function */ - setTemplateArgType(index: number, templateArgType: Type): void { return wrapJoinPoint(this._javaObject.setTemplateArgType(unwrapJoinPoint(index), unwrapJoinPoint(templateArgType))); } + newCall(args: Joinpoint[]): Call { return wrapJoinPoint(this._javaObject.newCall(unwrapJoinPoint(args))); } /** - * Sets the template argument types of a template type + * Sets the body of the function */ - setTemplateArgsTypes(templateArgTypes: Type[]): void { return wrapJoinPoint(this._javaObject.setTemplateArgsTypes(unwrapJoinPoint(templateArgTypes))); } + setBody(body: Scope): void { return wrapJoinPoint(this._javaObject.setBody(unwrapJoinPoint(body))); } /** - * Changes a single occurence of a type field that has the current value with new value. Returns true if there was a change + * Sets the type of the function */ - setTypeFieldByValueRecursive(currentValue: object, newValue: object): boolean { return wrapJoinPoint(this._javaObject.setTypeFieldByValueRecursive(unwrapJoinPoint(currentValue), unwrapJoinPoint(newValue))); } + setFunctionType(functionType: FunctionType): void { return wrapJoinPoint(this._javaObject.setFunctionType(unwrapJoinPoint(functionType))); } /** - * Replaces an underlying type of this instance with new type, if it matches the old type. Returns true if there were changes + * Sets the parameter of the function at the given position */ - setUnderlyingType(oldValue: Type, newValue: Type): Type { return wrapJoinPoint(this._javaObject.setUnderlyingType(unwrapJoinPoint(oldValue), unwrapJoinPoint(newValue))); } -} - + setParam(index: number, param: Param): void; /** - * Base node for declarations which introduce a typedef-name + * Sets the parameter of the function at the given position */ -export class TypedefNameDecl extends NamedDecl { + setParam(index: number, name: string, type?: Type): void; /** - * @internal + * Sets the parameter of the function at the given position */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; -} - + setParam(p1: number, p2: Param | string, p3?: Type): void { return wrapJoinPoint(this._javaObject.setParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2), unwrapJoinPoint(p3))); } /** - * Represents the type of a typedef. + * Sets the parameters of the function */ -export class TypedefType extends Type { + setParams(params: Param[]): void { return wrapJoinPoint(this._javaObject.setParams(unwrapJoinPoint(params))); } /** - * @internal + * Overload that accepts strings that represent type-varname pairs (e.g., int param1) */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; + setParamsFromStrings(params: string[]): void { return wrapJoinPoint(this._javaObject.setParamsFromStrings(unwrapJoinPoint(params))); } /** - * The typedef declaration associated with this typedef type + * Sets the type of a parameter of the function */ - get decl(): TypedefNameDecl { return wrapJoinPoint(this._javaObject.getDecl()) } + setParamType(index: number, newType: Type): void { return wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); } /** - * The type that is being typedef'd + * Sets the return type of the function */ - get underlyingType(): Type { return wrapJoinPoint(this._javaObject.getUnderlyingType()) } -} - -export class UnaryExprOrType extends Expression { + setReturnType(returnType: Type): void { return wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(returnType))); } /** - * @internal + * Sets the storage class of this specific function decl. AUTO and REGISTER are not allowed for functions, and EXTERN is not allowed in function implementations, or function declarations that are in the same file as the implementation. Returns true if the storage class changed, false otherwise */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get argExpr(): Expression { return wrapJoinPoint(this._javaObject.getArgExpr()) } - get argType(): Type { return wrapJoinPoint(this._javaObject.getArgType()) } - set argType(value: Type) { this._javaObject.setArgType(unwrapJoinPoint(value)); } - get hasArgExpr(): boolean { return wrapJoinPoint(this._javaObject.getHasArgExpr()) } - get hasTypeExpr(): boolean { return wrapJoinPoint(this._javaObject.getHasTypeExpr()) } - get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } - setArgType(argType: Type): void { return wrapJoinPoint(this._javaObject.setArgType(unwrapJoinPoint(argType))); } + setStorageClass(storageClass: StorageClass): boolean { return wrapJoinPoint(this._javaObject.setStorageClass(unwrapJoinPoint(storageClass))); } } -export class UnaryOp extends Op { /** - * @internal + * Represents a method in a class declaration */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get isPointerDeref(): boolean { return wrapJoinPoint(this._javaObject.getIsPointerDeref()) } - get operand(): Expression { return wrapJoinPoint(this._javaObject.getOperand()) } -} - -export class UndefinedType extends Type { +export class Method extends FunctionJp { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "name", }; + get record(): Class { return wrapJoinPoint(this._javaObject.record()) } + /** + * Removes the class of the method + */ + removeRecord(): void { return wrapJoinPoint(this._javaObject.removeRecord()); } } /** - * A reference to a variable + * Represents a pragma in the code (e.g., #pragma kernel) */ -export class Varref extends Expression { +export class Pragma extends Joinpoint { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; - get declaration(): Declarator { return wrapJoinPoint(this._javaObject.getDeclaration()) } /** - * True if this variable reference has a MS-style property, false otherwise + * Everything that is after the name of the pragma */ - get hasProperty(): boolean { return wrapJoinPoint(this._javaObject.getHasProperty()) } + get content(): string { return wrapJoinPoint(this._javaObject.content()) } /** - * True if this varref represents a function call + * Everything that is after the name of the pragma + */ + set content(value: string) { this._javaObject.setContent(unwrapJoinPoint(value)); } + /** + * The name of the pragma. E.g. for #pragma foo bar, returns 'foo' + */ + get name(): string { return wrapJoinPoint(this._javaObject.name()) } + /** + * The name of the pragma. E.g. for #pragma foo bar, returns 'foo' */ - get isFunctionCall(): boolean { return wrapJoinPoint(this._javaObject.getIsFunctionCall()) } - get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } /** - * If this variable reference has a MS-style property, returns the property name. Returns undefined otherwise + * The first node below the pragma that is not a comment or another pragma. Example of pragma targets are statements and declarations */ - get property(): string { return wrapJoinPoint(this._javaObject.getProperty()) } + get target(): Joinpoint { return wrapJoinPoint(this._javaObject.target()) } /** - * Expression from where the attribute 'use' is calculated. In certain cases (e.g., array access, pointer dereference) the 'use' attribute is not calculated on the node itself, but on an ancestor of the node. This attribute returns that node + * All the nodes below the target node, including the target node, up until a pragma with the name given by argument 'endPragma'. If no end pragma is found, returns the same result as if not providing the argument */ - get useExpr(): Expression { return wrapJoinPoint(this._javaObject.getUseExpr()) } + getTargetNodes(endPragma?: string): Joinpoint[] { return wrapJoinPoint(this._javaObject.getTargetNodes(unwrapJoinPoint(endPragma))); } + setContent(content: string): void { return wrapJoinPoint(this._javaObject.setContent(unwrapJoinPoint(content))); } setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } } -export class WrapperStmt extends Statement { /** - * @internal + * Represents a marker pragma, which is used to mark a specific node in the code (e.g., #pragma myMarker) and can be used to store custom data */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get content(): Joinpoint { return wrapJoinPoint(this._javaObject.getContent()) } - get kind(): "comment" | "pragma" { return wrapJoinPoint(this._javaObject.getKind()) } -} - -export class AccessSpecifier extends Decl { +export class Marker extends Pragma { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "kind", + name: "id", }; /** - * The type of specifier. Can return 'public', 'protected', 'private' or 'none' + * The scope that is targeted by the marker */ - get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } + get contents(): Scope { return wrapJoinPoint(this._javaObject.contents()) } + get id(): string { return wrapJoinPoint(this._javaObject.id()) } } -export class AdjustedType extends Type { + /** + * Represents a tag pragma, which is used to reference a specific node in the code + */ +export class Tag extends Pragma { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "id", }; - /** - * The type that is being adjusted - */ - get originalType(): Type { return wrapJoinPoint(this._javaObject.getOriginalType()) } + get id(): string { return wrapJoinPoint(this._javaObject.id()) } } -export class ArrayAccess extends Expression { + /** + * Represents an OpenMP pragma (e.g., #pragma omp parallel) + */ +export class Omp extends Pragma { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, + name: "kind", }; /** - * Expression representing the variable of the array access (can be a varref, memberAccess...) + * The names of the kinds of all clauses in the pragma, or empty array if no clause is defined */ - get arrayVar(): Expression { return wrapJoinPoint(this._javaObject.getArrayVar()) } + get clauseKinds(): string[] { return wrapJoinPoint(this._javaObject.clauseKinds()) } /** - * If the array access is done over a variable, returns the name of the variable. Equivalent to $arrayAccess.arrayVar.name - */ - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } - /** - * The number of subscripts of this array access - */ - get numSubscripts(): number { return wrapJoinPoint(this._javaObject.getNumSubscripts()) } - /** - * A view of the current arrayAccess without the last subscript, or undefined if this arrayAccess only has one subscript - */ - get parentAccess(): ArrayAccess { return wrapJoinPoint(this._javaObject.getParentAccess()) } - /** - * Expression of the array access subscript - */ - get subscript(): Expression[] { return wrapJoinPoint(this._javaObject.getSubscript()) } -} - -export class ArrayType extends Type { - /** - * @internal - */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get elementType(): Type { return wrapJoinPoint(this._javaObject.getElementType()) } - set elementType(value: Type) { this._javaObject.setElementType(unwrapJoinPoint(value)); } - /** - * Sets the element type of the array + * An integer expression, or undefined if no 'collapse' clause is defined */ - setElementType(arrayElementType: Type): void { return wrapJoinPoint(this._javaObject.setElementType(unwrapJoinPoint(arrayElementType))); } -} - -export class AsmStmt extends Statement { + get collapse(): string { return wrapJoinPoint(this._javaObject.collapse()) } /** - * @internal + * An integer expression, or undefined if no 'collapse' clause is defined */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get clobbers(): string[] { return wrapJoinPoint(this._javaObject.getClobbers()) } - get isSimple(): boolean { return wrapJoinPoint(this._javaObject.getIsSimple()) } - get isVolatile(): boolean { return wrapJoinPoint(this._javaObject.getIsVolatile()) } -} - -export class BinaryOp extends Op { + set collapse(value: string | number) { this._javaObject.setCollapse(unwrapJoinPoint(value)); } /** - * @internal + * The variable names of all copyin clauses, or empty array if no copyin clause is defined */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get isAssignment(): boolean { return wrapJoinPoint(this._javaObject.getIsAssignment()) } - get left(): Expression { return wrapJoinPoint(this._javaObject.getLeft()) } - set left(value: Expression) { this._javaObject.setLeft(unwrapJoinPoint(value)); } - get right(): Expression { return wrapJoinPoint(this._javaObject.getRight()) } - set right(value: Expression) { this._javaObject.setRight(unwrapJoinPoint(value)); } - setLeft(left: Expression): void { return wrapJoinPoint(this._javaObject.setLeft(unwrapJoinPoint(left))); } - setRight(right: Expression): void { return wrapJoinPoint(this._javaObject.setRight(unwrapJoinPoint(right))); } -} - -export class BoolLiteral extends Literal { + get copyin(): string[] { return wrapJoinPoint(this._javaObject.copyin()) } /** - * @internal + * The variable names of all copyin clauses, or empty array if no copyin clause is defined */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get value(): boolean { return wrapJoinPoint(this._javaObject.getValue()) } -} - -export class Break extends Statement { + set copyin(value: string[]) { this._javaObject.setCopyin(unwrapJoinPoint(value)); } /** - * @internal + * One of 'shared' or 'none', or undefined if no 'default' clause is defined */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; + get default(): string { return wrapJoinPoint(this._javaObject._default()) } /** - * The enclosing statement related to this break. It should be either a loop or a switch statement. + * One of 'shared' or 'none', or undefined if no 'default' clause is defined */ - get enclosingStmt(): Statement { return wrapJoinPoint(this._javaObject.getEnclosingStmt()) } -} - -export class BuiltinType extends Type { + set default(value: string) { this._javaObject.setDefault(unwrapJoinPoint(value)); } /** - * @internal + * The variable names of all firstprivate clauses, or empty array if no firstprivate clause is defined */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get builtinKind(): string { return wrapJoinPoint(this._javaObject.getBuiltinKind()) } + get firstprivate(): string[] { return wrapJoinPoint(this._javaObject.firstprivate()) } /** - * True, if ot is a floating type (e.g., float, double) + * The variable names of all firstprivate clauses, or empty array if no firstprivate clause is defined */ - get isFloat(): boolean { return wrapJoinPoint(this._javaObject.getIsFloat()) } + set firstprivate(value: string[]) { this._javaObject.setFirstprivate(unwrapJoinPoint(value)); } /** - * True, if it is an integer type + * The kind of the directive */ - get isInteger(): boolean { return wrapJoinPoint(this._javaObject.getIsInteger()) } + get kind(): string { return wrapJoinPoint(this._javaObject.kind()) } /** - * True, if it is a signed integer type + * The kind of the directive */ - get isSigned(): boolean { return wrapJoinPoint(this._javaObject.getIsSigned()) } + set kind(value: string) { this._javaObject.setKind(unwrapJoinPoint(value)); } /** - * True, if it is an unsigned integer type + * The variable names of all lastprivate clauses, or empty array if no lastprivate clause is defined */ - get isUnsigned(): boolean { return wrapJoinPoint(this._javaObject.getIsUnsigned()) } + get lastprivate(): string[] { return wrapJoinPoint(this._javaObject.lastprivate()) } /** - * True, if it is the type 'void' + * The variable names of all lastprivate clauses, or empty array if no lastprivate clause is defined */ - get isVoid(): boolean { return wrapJoinPoint(this._javaObject.getIsVoid()) } -} - -export class Call extends Expression { + set lastprivate(value: string[]) { this._javaObject.setLastprivate(unwrapJoinPoint(value)); } /** - * @internal + * An integer expression, or undefined if no 'num_threads' clause is defined */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; + get numThreads(): string { return wrapJoinPoint(this._javaObject.numThreads()) } /** - * An alias for 'args' + * An integer expression, or undefined if no 'num_threads' clause is defined */ - get argList(): Expression[] { return wrapJoinPoint(this._javaObject.getArgList()) } + set numThreads(value: string) { this._javaObject.setNumThreads(unwrapJoinPoint(value)); } /** - * An array with the arguments of the call + * An integer expression, or undefined if no 'ordered' clause with a parameter is defined */ - get args(): Expression[] { return wrapJoinPoint(this._javaObject.getArgs()) } + get ordered(): string { return wrapJoinPoint(this._javaObject.ordered()) } /** - * A 'function' join point that represents the function of the call that was found, it can return either an implementation or a function prototype; 'undefined' if no declaration was found + * An integer expression, or undefined if no 'ordered' clause with a parameter is defined */ - get declaration(): FunctionJp { return wrapJoinPoint(this._javaObject.getDeclaration()) } + set ordered(value: string) { this._javaObject.setOrdered(unwrapJoinPoint(value)); } /** - * A 'function' join point that represents the function definition of the call; 'undefined' if no definition was found + * The variable names of all private clauses, or empty array if no private clause is defined */ - get definition(): FunctionJp { return wrapJoinPoint(this._javaObject.getDefinition()) } + get private(): string[] { return wrapJoinPoint(this._javaObject._private()) } /** - * A function join point that represents the 'raw' function of the call (e.g. if this is a call to a templated function, returns a declaration representing the template specialization, instead of the original function) + * The variable names of all private clauses, or empty array if no private clause is defined */ - get directCallee(): FunctionJp { return wrapJoinPoint(this._javaObject.getDirectCallee()) } + set private(value: string[]) { this._javaObject.setPrivate(unwrapJoinPoint(value)); } /** - * A function join point associated with this call. If a definition is present, it is given priority over returning a declaration. If only declarations are present, returns a declaration + * One of 'master', 'close' or 'spread', or undefined if no 'proc_bind' clause is defined */ - get function(): FunctionJp { return wrapJoinPoint(this._javaObject.getFunction()) } + get procBind(): string { return wrapJoinPoint(this._javaObject.procBind()) } /** - * The function type of the call, which includes the return type and the types of the parameters + * One of 'master', 'close' or 'spread', or undefined if no 'proc_bind' clause is defined */ - get functionType(): FunctionType { return wrapJoinPoint(this._javaObject.getFunctionType()) } - get isMemberAccess(): boolean { return wrapJoinPoint(this._javaObject.getIsMemberAccess()) } - get isStmtCall(): boolean { return wrapJoinPoint(this._javaObject.getIsStmtCall()) } - get memberAccess(): MemberAccess { return wrapJoinPoint(this._javaObject.getMemberAccess()) } - get memberNames(): string[] { return wrapJoinPoint(this._javaObject.getMemberNames()) } - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } - set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } - get numArgs(): number { return wrapJoinPoint(this._javaObject.getNumArgs()) } + set procBind(value: string) { this._javaObject.setProcBind(unwrapJoinPoint(value)); } /** - * The return type of the call + * The reduction kinds in the reductions clauses of the this pragma, or empty array if no reduction is defined */ - get returnType(): Type { return wrapJoinPoint(this._javaObject.getReturnType()) } + get reductionKinds(): string[] { return wrapJoinPoint(this._javaObject.reductionKinds()) } /** - * Similar to $function.signature, but if no function decl could be found (e.g., function from system include), returns a signature based on just the name of the function + * An integer expression, or undefined if no 'schedule' clause with chunk size is defined */ - get signature(): string { return wrapJoinPoint(this._javaObject.getSignature()) } - getArg(index: number): Expression { return wrapJoinPoint(this._javaObject.getArg(unwrapJoinPoint(index))); } + get scheduleChunkSize(): string { return wrapJoinPoint(this._javaObject.scheduleChunkSize()) } /** - * Adds an argument at the end of the call, creating an expression using the given code and type. If a type is not provided, a dummy type is used + * An integer expression, or undefined if no 'schedule' clause with chunk size is defined */ - addArg(argCode: string, type?: Type): void; + set scheduleChunkSize(value: string | number) { this._javaObject.setScheduleChunkSize(unwrapJoinPoint(value)); } /** - * Adds an argument at the end of the call, creating a literal 'type' from the type string + * One of 'static', 'dynamic', 'guided', 'auto' or 'runtime', or undefined if no 'schedule' clause is defined */ - addArg(arg: string, type: string): void; + get scheduleKind(): string { return wrapJoinPoint(this._javaObject.scheduleKind()) } /** - * Adds an argument at the end of the call, creating an expression using the given code and type. If a type is not provided, a dummy type is used + * One of 'static', 'dynamic', 'guided', 'auto' or 'runtime', or undefined if no 'schedule' clause is defined */ - addArg(p1: string, p2?: Type | string): void { return wrapJoinPoint(this._javaObject.addArg(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + set scheduleKind(value: string) { this._javaObject.setScheduleKind(unwrapJoinPoint(value)); } /** - * Tries to inline this call + * A list with possible values of 'monotonic', 'nonmonotonic' or 'simd', or undefined if no 'schedule' clause with modifiers is defined */ - inline(): boolean { return wrapJoinPoint(this._javaObject.inline()); } - setArg(index: number, expr: Expression): void { return wrapJoinPoint(this._javaObject.setArg(unwrapJoinPoint(index), unwrapJoinPoint(expr))); } - setArgFromString(index: number, expr: string): void { return wrapJoinPoint(this._javaObject.setArgFromString(unwrapJoinPoint(index), unwrapJoinPoint(expr))); } + get scheduleModifiers(): string[] { return wrapJoinPoint(this._javaObject.scheduleModifiers()) } /** - * Changes the name of the call + * A list with possible values of 'monotonic', 'nonmonotonic' or 'simd', or undefined if no 'schedule' clause with modifiers is defined */ - setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } + set scheduleModifiers(value: string[]) { this._javaObject.setScheduleModifiers(unwrapJoinPoint(value)); } /** - * Wraps this call with a possibly new wrapping function + * The variable names of all shared clauses, or empty array if no shared clause is defined */ - wrap(name: string): void { return wrapJoinPoint(this._javaObject.wrap(unwrapJoinPoint(name))); } -} - -export class Case extends SwitchCase { + get shared(): string[] { return wrapJoinPoint(this._javaObject.shared()) } /** - * @internal + * The variable names of all shared clauses, or empty array if no shared clause is defined */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; + set shared(value: string[]) { this._javaObject.setShared(unwrapJoinPoint(value)); } /** - * The instructions that are associated with this case in the source code. This does not represent what instructions are actually executed (e.g., if a case does not have a break, does not show instructions of the next case) + * The variable names for the given reduction kind, or empty array if no reduction of that kind is defined */ - get instructions(): Statement[] { return wrapJoinPoint(this._javaObject.getInstructions()) } + getReduction(kind: string): string[] { return wrapJoinPoint(this._javaObject.getReduction(unwrapJoinPoint(kind))); } /** - * True if this is a default case, false otherwise + * True if the directive has at least one clause of the given clause kind, false otherwise */ - get isDefault(): boolean { return wrapJoinPoint(this._javaObject.getIsDefault()) } + hasClause(clauseName: string): boolean { return wrapJoinPoint(this._javaObject.hasClause(unwrapJoinPoint(clauseName))); } /** - * True if this case does not contain instructions (i.e., it is directly above another case), false otherwise + * True if the directive has the given clause kind, false otherwise */ - get isEmpty(): boolean { return wrapJoinPoint(this._javaObject.getIsEmpty()) } + isClauseLegal(clauseName: string): boolean { return wrapJoinPoint(this._javaObject.isClauseLegal(unwrapJoinPoint(clauseName))); } /** - * The case statement that comes after this case, or undefined if there are no more case statements + * Removes any clause of the given kind from the OpenMP pragma */ - get nextCase(): Case { return wrapJoinPoint(this._javaObject.getNextCase()) } + removeClause(clauseKind: string): void { return wrapJoinPoint(this._javaObject.removeClause(unwrapJoinPoint(clauseKind))); } /** - * The first statement that is not a case that will be executed by this case statement + * Sets the value of the collapse clause of an OpenMP pragma */ - get nextInstruction(): Statement { return wrapJoinPoint(this._javaObject.getNextInstruction()) } + setCollapse(newExpr: string): void; /** - * The values that the case statement will match. It can return zero (e.g., 'default:'), one (e.g., 'case 1:') or two (e.g., 'case 2...4:') expressions, depending on the format of the case + * Sets the value of the collapse clause of an OpenMP pragma */ - get values(): Expression[] { return wrapJoinPoint(this._javaObject.getValues()) } -} - -export class Cast extends Expression { + setCollapse(newExpr: number): void; /** - * @internal + * Sets the value of the collapse clause of an OpenMP pragma */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get fromType(): Type { return wrapJoinPoint(this._javaObject.getFromType()) } + setCollapse(p1: string | number): void { return wrapJoinPoint(this._javaObject.setCollapse(unwrapJoinPoint(p1))); } /** - * @deprecated Use expr.implicitCast instead + * Sets the variables of a copyin clause of an OpenMP pragma */ - get isImplicitCast(): boolean { return wrapJoinPoint(this._javaObject.getIsImplicitCast()) } - get subExpr(): Expression { return wrapJoinPoint(this._javaObject.getSubExpr()) } - get toType(): Type { return wrapJoinPoint(this._javaObject.getToType()) } -} - -export class CilkSpawn extends Call { + setCopyin(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setCopyin(unwrapJoinPoint(newVariables))); } /** - * @internal + * Sets the value of the default clause of an OpenMP pragma */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; -} - -export class CilkSync extends Statement { + setDefault(newDefault: string): void { return wrapJoinPoint(this._javaObject.setDefault(unwrapJoinPoint(newDefault))); } /** - * @internal + * Sets the variables of a firstprivate clause of an OpenMP pragma */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; -} - + setFirstprivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setFirstprivate(unwrapJoinPoint(newVariables))); } /** - * Represents a C++ class + * Sets the directive kind of the OpenMP pragma. Any unsupported clauses will be discarded */ -export class Class extends RecordJp { + setKind(directiveKind: string): void { return wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(directiveKind))); } /** - * @internal + * Sets the variables of a lastprivate clause of an OpenMP pragma */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; + setLastprivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setLastprivate(unwrapJoinPoint(newVariables))); } /** - * All the classes this class inherits from + * Sets the value of the num_threads clause of an OpenMP pragma */ - get allBases(): Class[] { return wrapJoinPoint(this._javaObject.getAllBases()) } + setNumThreads(newExpr: string): void { return wrapJoinPoint(this._javaObject.setNumThreads(unwrapJoinPoint(newExpr))); } /** - * All the methods of this class, including inherited ones + * Sets the value of the ordered clause of an OpenMP pragma */ - get allMethods(): Method[] { return wrapJoinPoint(this._javaObject.getAllMethods()) } + setOrdered(parameters?: string): void { return wrapJoinPoint(this._javaObject.setOrdered(unwrapJoinPoint(parameters))); } /** - * The classes this class directly inherits from + * Sets the variables of a private clause of an OpenMP pragma */ - get bases(): Class[] { return wrapJoinPoint(this._javaObject.getBases()) } + setPrivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setPrivate(unwrapJoinPoint(newVariables))); } /** - * Class join points can either represent declarations or definitions, returns the definition of this class, if present, or the first declaration, if only declarations are present + * Sets the value of the proc_bind clause of an OpenMP pragma */ - get canonical(): Class { return wrapJoinPoint(this._javaObject.getCanonical()) } + setProcBind(newBind: string): void { return wrapJoinPoint(this._javaObject.setProcBind(unwrapJoinPoint(newBind))); } /** - * The implementation (or definition) of this class present in the AST, or undefined if none is found + * Sets the variables for a given kind of a reduction clause of an OpenMP pragma */ - get implementation(): Class { return wrapJoinPoint(this._javaObject.getImplementation()) } + setReduction(kind: string, newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setReduction(unwrapJoinPoint(kind), unwrapJoinPoint(newVariables))); } /** - * True, if contains at least one pure function + * Sets the value of the chunk size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception */ - get isAbstract(): boolean { return wrapJoinPoint(this._javaObject.getIsAbstract()) } + setScheduleChunkSize(chunkSize: string): void; /** - * True if this is the class returned by the 'canonical' attribute + * Sets the value of the chunk size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception */ - get isCanonical(): boolean { return wrapJoinPoint(this._javaObject.getIsCanonical()) } + setScheduleChunkSize(chunkSize: number): void; /** - * True, if all functions are pure + * Sets the value of the chunk size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception */ - get isInterface(): boolean { return wrapJoinPoint(this._javaObject.getIsInterface()) } + setScheduleChunkSize(p1: string | number): void { return wrapJoinPoint(this._javaObject.setScheduleChunkSize(unwrapJoinPoint(p1))); } /** - * The methods declared by this class + * Sets the value of the schedule clause of an OpenMP pragma */ - get methods(): Method[] { return wrapJoinPoint(this._javaObject.getMethods()) } + setScheduleKind(scheduleKind: string): void { return wrapJoinPoint(this._javaObject.setScheduleKind(unwrapJoinPoint(scheduleKind))); } /** - * The prototypes (or declarations) of this class present in the AST, if any + * Sets the value of the modifiers in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception */ - get prototypes(): Class[] { return wrapJoinPoint(this._javaObject.getPrototypes()) } + setScheduleModifiers(modifiers: string[]): void { return wrapJoinPoint(this._javaObject.setScheduleModifiers(unwrapJoinPoint(modifiers))); } /** - * Adds a method to a class. If the given method has a definition, creates an equivalent declaration and adds it to the class, otherwise simply added the declaration to the class. In both cases, the declaration is only added to the class if there is no declaration already with the same signature. + * Sets the variables of a shared clause of an OpenMP pragma */ - addMethod(method: Method): void { return wrapJoinPoint(this._javaObject.addMethod(unwrapJoinPoint(method))); } + setShared(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setShared(unwrapJoinPoint(newVariables))); } } -export class Continue extends Statement { +export class Statement extends Joinpoint { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; + get isFirst(): boolean { return wrapJoinPoint(this._javaObject.isFirst()) } + get isLast(): boolean { return wrapJoinPoint(this._javaObject.isLast()) } } -export class CudaKernelCall extends Call { /** - * @internal + * Represents a group of statements (e.g., function body, loop body, if/else body, etc.) */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; - get config(): Expression[] { return wrapJoinPoint(this._javaObject.getConfig()) } - set config(value: Expression[]) { this._javaObject.setConfig(unwrapJoinPoint(value)); } - setConfig(args: Expression[]): void { return wrapJoinPoint(this._javaObject.setConfig(unwrapJoinPoint(args))); } - setConfigFromStrings(args: string[]): void { return wrapJoinPoint(this._javaObject.setConfigFromStrings(unwrapJoinPoint(args))); } -} - -export class DeclStmt extends Statement { +export class Scope extends Statement { /** * @internal */ @@ -1746,330 +1616,209 @@ export class DeclStmt extends Statement { name: null, }; /** - * The declarations in this statement + * Returns the descendant statements of this scope, excluding other scopes, loops, ifs and wrapper statements */ - get decls(): Decl[] { return wrapJoinPoint(this._javaObject.getDecls()) } -} - + get allStmts(): Statement[] { return wrapJoinPoint(this._javaObject.allStmts()) } /** - * Represents a decl that comes from a declarator (e.g., function, field, variable) + * Returns the first statement in the scope */ -export class Declarator extends NamedDecl { + get firstStmt(): Statement { return wrapJoinPoint(this._javaObject.firstStmt()) } /** - * @internal + * Returns the last statement in the scope */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; -} - -export class Default extends SwitchCase { + get lastStmt(): Statement { return wrapJoinPoint(this._javaObject.lastStmt()) } /** - * @internal + * True if the scope does not have curly braces */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; -} - -export class DeleteExpr extends Expression { - /** - * @internal - */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; -} - - /** - * Represents a type that was referred to using an elaborated type keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, or both. This type is used to keep track of a type name as written in the source code, including tag keywords and any nested-name-specifiers. The type itself is always 'sugar', used to express what was written in the source code but containing no additional semantic information. - */ -export class ElaboratedType extends Type { + get naked(): boolean { return wrapJoinPoint(this._javaObject.naked()) } /** - * @internal + * True if the scope does not have curly braces */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; + set naked(value: boolean) { this._javaObject.setNaked(unwrapJoinPoint(value)); } /** - * The keyword of this elaborated type, if present. Can be one of: struct, interface, union, class, enum, typename + * The statement that owns the scope (e.g., function, loop...) */ - get keyword(): string { return wrapJoinPoint(this._javaObject.getKeyword()) } + get owner(): Joinpoint { return wrapJoinPoint(this._javaObject.owner()) } /** - * The type that is being prefixed with the qualifier + * Returns the direct (children) statements of this scope */ - get namedType(): Type { return wrapJoinPoint(this._javaObject.getNamedType()) } + get stmts(): Statement[] { return wrapJoinPoint(this._javaObject.stmts()) } /** - * The qualifier of this elaborated type, if present (e.g., A::) + * Adds a new local variable to this scope */ - get qualifier(): string { return wrapJoinPoint(this._javaObject.getQualifier()) } -} - -export class EmptyStmt extends Statement { + addLocal(name: string, type: Joinpoint, initValue?: string): Joinpoint { return wrapJoinPoint(this._javaObject.addLocal(unwrapJoinPoint(name), unwrapJoinPoint(type), unwrapJoinPoint(initValue))); } /** - * @internal + * CFG tester */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; -} - + cfg(): string { return wrapJoinPoint(this._javaObject.cfg()); } /** - * Represents an enum + * Clears the contents of this scope (untested) */ -export class EnumDecl extends NamedDecl { + clear(): void { return wrapJoinPoint(this._javaObject.clear()); } /** - * @internal + * DFG tester */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; - get enumerators(): EnumeratorDecl[] { return wrapJoinPoint(this._javaObject.getEnumerators()) } -} - -export class EnumeratorDecl extends NamedDecl { + dfg(): string { return wrapJoinPoint(this._javaObject.dfg()); } /** - * @internal + * The number of statements in the scope, including the statements inside the declaration and bodies of structures such as ifs and loops, and not considering comments and pragmas. If flat is true, does not consider the statements inside structures such as ifs and loops (e.g., a loop counts as one statement) */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; -} - -export class ExprStmt extends Statement { + getNumStatements(flat: boolean = false): number { return wrapJoinPoint(this._javaObject.getNumStatements(unwrapJoinPoint(flat))); } + insertBegin(node: Joinpoint): Joinpoint; + insertBegin(code: string): Joinpoint; + insertBegin(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertBegin(unwrapJoinPoint(p1))); } + insertEnd(node: Joinpoint): Joinpoint; + insertEnd(code: string): Joinpoint; + insertEnd(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertEnd(unwrapJoinPoint(p1))); } /** - * @internal + * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; + insertReturn(code: Joinpoint): Joinpoint; /** - * The expression join point associated to this exprStmt + * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node */ - get expr(): Expression { return wrapJoinPoint(this._javaObject.getExpr()) } -} - + insertReturn(code: string): Joinpoint; /** - * Represents a member of a struct/union/class + * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node */ -export class Field extends Declarator { + insertReturn(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); } /** - * @internal + * Sets the 'naked' status of a scope (a scope is naked if it does not have curly braces) */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", - }; + setNaked(isNaked: boolean): void { return wrapJoinPoint(this._javaObject.setNaked(unwrapJoinPoint(isNaked))); } } -export class FloatLiteral extends Literal { +export class Body extends Scope { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get value(): number { return wrapJoinPoint(this._javaObject.getValue()) } } - /** - * Represents a function declaration or definition - */ -export class FunctionJp extends Declarator { +export class Loop extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", + name: "kind", }; - get body(): Scope { return wrapJoinPoint(this._javaObject.getBody()) } + get body(): Scope { return wrapJoinPoint(this._javaObject.body()) } set body(value: Scope) { this._javaObject.setBody(unwrapJoinPoint(value)); } - get calls(): Call[] { return wrapJoinPoint(this._javaObject.getCalls()) } - /** - * Function join points can either represent declarations or definitions, returns the definition of this function, if present, or the first declaration, if only declarations are present - */ - get canonical(): FunctionJp { return wrapJoinPoint(this._javaObject.getCanonical()) } - /** - * Returns the first prototype of this function that could be found, or undefined if there is none - */ - get declarationJp(): FunctionJp { return wrapJoinPoint(this._javaObject.getDeclarationJp()) } - /** - * Returns the prototypes of this function that are present in the code. If there are none, returns an empty array - */ - get declarationJps(): FunctionJp[] { return wrapJoinPoint(this._javaObject.getDeclarationJps()) } - /** - * Returns the implementation of this function if there is one, or undefined otherwise - */ - get definitionJp(): FunctionJp { return wrapJoinPoint(this._javaObject.getDefinitionJp()) } - /** - * The type of the call, which includes the return type and the types of the parameters - */ - get functionType(): FunctionType { return wrapJoinPoint(this._javaObject.getFunctionType()) } /** - * The type of the call, which includes the return type and the types of the parameters - */ - set functionType(value: FunctionType) { this._javaObject.setFunctionType(unwrapJoinPoint(value)); } - /** - * True if this particular function join point has a body, false otherwise - * - * @deprecated Use .isImplementation instead - */ - get hasDefinition(): boolean { return wrapJoinPoint(this._javaObject.getHasDefinition()) } - get id(): string { return wrapJoinPoint(this._javaObject.getId()) } - /** - * True, if this is the function returned by the 'canonical' attribute - */ - get isCanonical(): boolean { return wrapJoinPoint(this._javaObject.getIsCanonical()) } - get isCudaKernel(): boolean { return wrapJoinPoint(this._javaObject.getIsCudaKernel()) } - get isDelete(): boolean { return wrapJoinPoint(this._javaObject.getIsDelete()) } - /** - * True if this particular function join point is an implementation (i.e. has a body), false otherwise - */ - get isImplementation(): boolean { return wrapJoinPoint(this._javaObject.getIsImplementation()) } - get isInline(): boolean { return wrapJoinPoint(this._javaObject.getIsInline()) } - get isModulePrivate(): boolean { return wrapJoinPoint(this._javaObject.getIsModulePrivate()) } - /** - * True if this particular function join point is a prototype (i.e. does not have a body), false otherwise + * The statement of the loop condition */ - get isPrototype(): boolean { return wrapJoinPoint(this._javaObject.getIsPrototype()) } - get isPure(): boolean { return wrapJoinPoint(this._javaObject.getIsPure()) } - get isVirtual(): boolean { return wrapJoinPoint(this._javaObject.getIsVirtual()) } - get paramNames(): string[] { return wrapJoinPoint(this._javaObject.getParamNames()) } - get params(): Param[] { return wrapJoinPoint(this._javaObject.getParams()) } - set params(value: Param[]) { this._javaObject.setParams(unwrapJoinPoint(value)); } - get returnType(): Type { return wrapJoinPoint(this._javaObject.getReturnType()) } - set returnType(value: Type) { this._javaObject.setReturnType(unwrapJoinPoint(value)); } + get cond(): Statement { return wrapJoinPoint(this._javaObject.cond()) } /** - * A string with the signature of this function (e.g., name of the function, plus the parameters types) + * The statement of the loop condition */ - get signature(): string { return wrapJoinPoint(this._javaObject.getSignature()) } + set cond(value: string) { this._javaObject.setCond(unwrapJoinPoint(value)); } + get condRelation(): Relation { return wrapJoinPoint(this._javaObject.condRelation()) } + set condRelation(value: Relation) { this._javaObject.setCondRelation(unwrapJoinPoint(value)); } + get controlVar(): string { return wrapJoinPoint(this._javaObject.controlVar()) } + get controlVarref(): Varref { return wrapJoinPoint(this._javaObject.controlVarref()) } /** - * The storage class of this function (i.e., one of NONE, EXTERN, PRIVATE_EXTERN or STATIC) + * The expression of the last value of the control variable (e.g. '10' in 'size_t i = 0; i < 10; i++') */ - get storageClass(): StorageClass { return wrapJoinPoint(this._javaObject.getStorageClass()) } + get endValue(): string { return wrapJoinPoint(this._javaObject.endValue()) } /** - * The storage class of this function (i.e., one of NONE, EXTERN, PRIVATE_EXTERN or STATIC) + * The expression of the last value of the control variable (e.g. '10' in 'size_t i = 0; i < 10; i++') */ - set storageClass(value: StorageClass) { this._javaObject.setStorageClass(unwrapJoinPoint(value)); } - getDeclaration(withReturnType: boolean): string { return wrapJoinPoint(this._javaObject.getDeclaration(unwrapJoinPoint(withReturnType))); } + set endValue(value: string) { this._javaObject.setEndValue(unwrapJoinPoint(value)); } /** - * Adds a new parameter to the function + * True if the condition of the loop in the canonical format, and is one of: <, <=, >, >= */ - addParam(param: Param): void; + get hasCondRelation(): boolean { return wrapJoinPoint(this._javaObject.hasCondRelation()) } /** - * Adds a new parameter to the function + * Uniquely identifies the loop inside the program */ - addParam(name: string, type?: Type): void; + get id(): string { return wrapJoinPoint(this._javaObject.id()) } /** - * Adds a new parameter to the function + * The statement of the loop initialization */ - addParam(p1: Param | string, p2?: Type): void { return wrapJoinPoint(this._javaObject.addParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + get init(): Statement { return wrapJoinPoint(this._javaObject.init()) } /** - * Clones this function assigning it a new name, inserts the cloned function after the original function. If the name is the same and the original method, automatically removes the cloned method from the class + * The statement of the loop initialization */ - clone(newName: string, insert: boolean = true): FunctionJp { return wrapJoinPoint(this._javaObject.clone(unwrapJoinPoint(newName), unwrapJoinPoint(insert))); } + set init(value: string) { this._javaObject.setInit(unwrapJoinPoint(value)); } /** - * Generates a clone of the provided function on a new file with the provided name (or with a weaver-generated name if one is not provided). + * The expression of the first value of the control variable (e.g. '0' in 'size_t i = 0;') */ - cloneOnFile(newName: string, fileName?: string): FunctionJp; + get initValue(): string { return wrapJoinPoint(this._javaObject.initValue()) } /** - * Generates a clone of the provided function on a new file (with the provided join point). + * The expression of the first value of the control variable (e.g. '0' in 'size_t i = 0;') */ - cloneOnFile(newName: string, fileName: FileJp): FunctionJp; + set initValue(value: string) { this._javaObject.setInitValue(unwrapJoinPoint(value)); } + get isInnermost(): boolean { return wrapJoinPoint(this._javaObject.isInnermost()) } + get isOutermost(): boolean { return wrapJoinPoint(this._javaObject.isOutermost()) } + get isParallel(): boolean { return wrapJoinPoint(this._javaObject.isParallel()) } + set isParallel(value: boolean) { this._javaObject.setIsParallel(unwrapJoinPoint(value)); } + get iterations(): number { return wrapJoinPoint(this._javaObject.iterations()) } + get iterationsExpr(): Expression { return wrapJoinPoint(this._javaObject.iterationsExpr()) } + get kind(): LoopKind { return wrapJoinPoint(this._javaObject.kind()) } + set kind(value: LoopKind) { this._javaObject.setKind(unwrapJoinPoint(value)); } + get nestedLevel(): number { return wrapJoinPoint(this._javaObject.nestedLevel()) } + get rank(): number[] { return wrapJoinPoint(this._javaObject.rank()) } /** - * Generates a clone of the provided function on a new file with the provided name (or with a weaver-generated name if one is not provided). + * The statement of the loop step */ - cloneOnFile(p1: string, p2?: string | FileJp): FunctionJp { return wrapJoinPoint(this._javaObject.cloneOnFile(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + get step(): Statement { return wrapJoinPoint(this._javaObject.step()) } /** - * Inserts the joinpoint before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node + * The statement of the loop step */ - insertReturn(code: Joinpoint): Joinpoint; + set step(value: string) { this._javaObject.setStep(unwrapJoinPoint(value)); } /** - * Inserts code as a literal statement before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node + * The expression of the step value of the control variable (e.g. '1' in 'size_t i = 0; i < 10; i++') */ - insertReturn(code: string): Joinpoint; + get stepValue(): string { return wrapJoinPoint(this._javaObject.stepValue()) } /** - * Inserts the joinpoint before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node + * Interchanges two for loops, if possible */ - insertReturn(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); } + interchange(otherLoop: Loop): void { return wrapJoinPoint(this._javaObject.interchange(unwrapJoinPoint(otherLoop))); } /** - * Creates a new call to this function + * True if this loop can be interchanged with the given loop, which means that they are adjacent and have no data dependencies that would prevent their interchange. This is a conservative test. */ - newCall(args: Joinpoint[]): Call { return wrapJoinPoint(this._javaObject.newCall(unwrapJoinPoint(args))); } + isInterchangeable(otherLoop: Loop): boolean { return wrapJoinPoint(this._javaObject.isInterchangeable(unwrapJoinPoint(otherLoop))); } /** - * Sets the body of the function + * Sets the body of the loop */ setBody(body: Scope): void { return wrapJoinPoint(this._javaObject.setBody(unwrapJoinPoint(body))); } /** - * Sets the type of the function - */ - setFunctionType(functionType: FunctionType): void { return wrapJoinPoint(this._javaObject.setFunctionType(unwrapJoinPoint(functionType))); } - /** - * Sets the parameter of the function at the given position - */ - setParam(index: number, param: Param): void; - /** - * Sets the parameter of the function at the given position - */ - setParam(index: number, name: string, type?: Type): void; - /** - * Sets the parameter of the function at the given position - */ - setParam(p1: number, p2: Param | string, p3?: Type): void { return wrapJoinPoint(this._javaObject.setParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2), unwrapJoinPoint(p3))); } - /** - * Sets the type of a parameter of the function - */ - setParamType(index: number, newType: Type): void { return wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); } - /** - * Sets the parameters of the function + * Sets the conditional statement of the loop. Works with loops of kind 'for' */ - setParams(params: Param[]): void { return wrapJoinPoint(this._javaObject.setParams(unwrapJoinPoint(params))); } + setCond(condCode: string): void { return wrapJoinPoint(this._javaObject.setCond(unwrapJoinPoint(condCode))); } /** - * Overload that accepts strings that represent type-varname pairs (e.g., int param1) + * Changes the operator of a canonical condition, if possible. Supported operators: lt, le, gt, ge */ - setParamsFromStrings(params: string[]): void { return wrapJoinPoint(this._javaObject.setParamsFromStrings(unwrapJoinPoint(params))); } + setCondRelation(operator: Relation): void { return wrapJoinPoint(this._javaObject.setCondRelation(unwrapJoinPoint(operator))); } /** - * Sets the return type of the function + * Sets the end value of the loop. Works with loops of kind 'for' */ - setReturnType(returnType: Type): void { return wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(returnType))); } + setEndValue(initCode: string): void { return wrapJoinPoint(this._javaObject.setEndValue(unwrapJoinPoint(initCode))); } /** - * Sets the storage class of this specific function decl. AUTO and REGISTER are not allowed for functions, and EXTERN is not allowed in function implementations, or function declarations that are in the same file as the implementation. Returns true if the storage class changed, false otherwise. + * Sets the init statement of the loop */ - setStorageClass(storageClass: StorageClass): boolean { return wrapJoinPoint(this._javaObject.setStorageClass(unwrapJoinPoint(storageClass))); } -} - -export class FunctionType extends Type { + setInit(initCode: string): void { return wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(initCode))); } /** - * @internal + * Sets the init value of the loop. Works with loops of kind 'for' */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get paramTypes(): Type[] { return wrapJoinPoint(this._javaObject.getParamTypes()) } - get returnType(): Type { return wrapJoinPoint(this._javaObject.getReturnType()) } - set returnType(value: Type) { this._javaObject.setReturnType(unwrapJoinPoint(value)); } + setInitValue(initCode: string): void { return wrapJoinPoint(this._javaObject.setInitValue(unwrapJoinPoint(initCode))); } /** - * Sets the type of a parameter of the FunctionType. Be careful that if you directly change the type of a paramemter and the function type is associated with a function declaration, this change will not be reflected in the function. If you want to change the type of a parameter of a function declaration, use $function.setParaType + * Sets the attribute 'isParallel' of the loop */ - setParamType(index: number, newType: Type): void { return wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); } + setIsParallel(isParallel: boolean): void { return wrapJoinPoint(this._javaObject.setIsParallel(unwrapJoinPoint(isParallel))); } /** - * Sets the return type of the FunctionType + * Sets the kind of the loop */ - setReturnType(newType: Type): void { return wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(newType))); } -} - -export class GotoStmt extends Statement { + setKind(kind: LoopKind): void { return wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(kind))); } /** - * @internal + * Sets the step statement of the loop. Works with loops of kind 'for' */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: null, - }; - get label(): LabelDecl { return wrapJoinPoint(this._javaObject.getLabel()) } - set label(value: LabelDecl) { this._javaObject.setLabel(unwrapJoinPoint(value)); } + setStep(stepCode: string): void { return wrapJoinPoint(this._javaObject.setStep(unwrapJoinPoint(stepCode))); } /** - * Sets the label of the goto + * Applies loop tiling to this loop */ - setLabel(label: LabelDecl): void { return wrapJoinPoint(this._javaObject.setLabel(unwrapJoinPoint(label))); } + tile(blockSize: string, reference: Statement, useTernary: boolean = true): Statement { return wrapJoinPoint(this._javaObject.tile(unwrapJoinPoint(blockSize), unwrapJoinPoint(reference), unwrapJoinPoint(useTernary))); } } export class If extends Statement { @@ -2079,12 +1828,12 @@ export class If extends Statement { static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get cond(): Expression { return wrapJoinPoint(this._javaObject.getCond()) } + get cond(): Expression { return wrapJoinPoint(this._javaObject.cond()) } set cond(value: Expression) { this._javaObject.setCond(unwrapJoinPoint(value)); } - get condDecl(): Vardecl { return wrapJoinPoint(this._javaObject.getCondDecl()) } - get else(): Scope { return wrapJoinPoint(this._javaObject.getElse()) } + get condDecl(): Vardecl { return wrapJoinPoint(this._javaObject.condDecl()) } + get else(): Scope { return wrapJoinPoint(this._javaObject._else()) } set else(value: Statement) { this._javaObject.setElse(unwrapJoinPoint(value)); } - get then(): Scope { return wrapJoinPoint(this._javaObject.getThen()) } + get then(): Scope { return wrapJoinPoint(this._javaObject.then()) } set then(value: Statement) { this._javaObject.setThen(unwrapJoinPoint(value)); } /** * Sets the condition of the if @@ -2100,702 +1849,913 @@ export class If extends Statement { setThen(then: Statement): void { return wrapJoinPoint(this._javaObject.setThen(unwrapJoinPoint(then))); } } -export class IncompleteArrayType extends ArrayType { +export class WrapperStmt extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; + get content(): Joinpoint { return wrapJoinPoint(this._javaObject.content()) } + get kind(): WrapperStatementKind { return wrapJoinPoint(this._javaObject.kind()) } } -export class IntLiteral extends Literal { +export class ReturnStmt extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get value(): number { return wrapJoinPoint(this._javaObject.getValue()) } + get returnExpr(): Expression { return wrapJoinPoint(this._javaObject.returnExpr()) } } -export class LabelDecl extends NamedDecl { +export class Switch extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", + name: null, }; - get labelStmt(): LabelStmt { return wrapJoinPoint(this._javaObject.getLabelStmt()) } + /** + * The case statements inside this switch + */ + get cases(): Case[] { return wrapJoinPoint(this._javaObject.cases()) } + get condition(): Expression { return wrapJoinPoint(this._javaObject.condition()) } + /** + * The default case statement of this switch statement or undefined if it does not have a default case + */ + get getDefaultCase(): Case { return wrapJoinPoint(this._javaObject.getDefaultCase()) } + /** + * True if there is a default case in this switch statement, false otherwise + */ + get hasDefaultCase(): boolean { return wrapJoinPoint(this._javaObject.hasDefaultCase()) } } -export class LabelStmt extends Statement { +export class SwitchCase extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get decl(): LabelDecl { return wrapJoinPoint(this._javaObject.getDecl()) } - set decl(value: LabelDecl) { this._javaObject.setDecl(unwrapJoinPoint(value)); } - /** - * Sets the label of the label statement - */ - setDecl(label: LabelDecl): void { return wrapJoinPoint(this._javaObject.setDecl(unwrapJoinPoint(label))); } -} - -export class Loop extends Statement { +} + +export class Case extends SwitchCase { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "kind", + name: null, }; - get body(): Scope { return wrapJoinPoint(this._javaObject.getBody()) } - set body(value: Scope) { this._javaObject.setBody(unwrapJoinPoint(value)); } - /** - * The statement of the loop condition - */ - get cond(): Statement { return wrapJoinPoint(this._javaObject.getCond()) } - /** - * The statement of the loop condition - */ - set cond(value: string) { this._javaObject.setCond(unwrapJoinPoint(value)); } - get condRelation(): Relation { return wrapJoinPoint(this._javaObject.getCondRelation()) } - set condRelation(value: Relation) { this._javaObject.setCondRelation(unwrapJoinPoint(value)); } - get controlVar(): string { return wrapJoinPoint(this._javaObject.getControlVar()) } - get controlVarref(): Varref { return wrapJoinPoint(this._javaObject.getControlVarref()) } - /** - * The expression of the last value of the control variable (e.g. 'length' in 'i < length;') - */ - get endValue(): string { return wrapJoinPoint(this._javaObject.getEndValue()) } - /** - * The expression of the last value of the control variable (e.g. 'length' in 'i < length;') - */ - set endValue(value: string) { this._javaObject.setEndValue(unwrapJoinPoint(value)); } - /** - * True if the condition of the loop in the canonical format, and is one of: <, <=, >, >= - */ - get hasCondRelation(): boolean { return wrapJoinPoint(this._javaObject.getHasCondRelation()) } - /** - * Uniquely identifies the loop inside the program - */ - get id(): string { return wrapJoinPoint(this._javaObject.getId()) } - /** - * The statement of the loop initialization - */ - get init(): Statement { return wrapJoinPoint(this._javaObject.getInit()) } /** - * The statement of the loop initialization - */ - set init(value: string) { this._javaObject.setInit(unwrapJoinPoint(value)); } - /** - * The expression of the first value of the control variable (e.g. '0' in 'size_t i = 0;') - */ - get initValue(): string { return wrapJoinPoint(this._javaObject.getInitValue()) } - /** - * The expression of the first value of the control variable (e.g. '0' in 'size_t i = 0;') - */ - set initValue(value: string) { this._javaObject.setInitValue(unwrapJoinPoint(value)); } - get isInnermost(): boolean { return wrapJoinPoint(this._javaObject.getIsInnermost()) } - get isOutermost(): boolean { return wrapJoinPoint(this._javaObject.getIsOutermost()) } - get isParallel(): boolean { return wrapJoinPoint(this._javaObject.getIsParallel()) } - set isParallel(value: boolean) { this._javaObject.setIsParallel(unwrapJoinPoint(value)); } - get iterations(): number { return wrapJoinPoint(this._javaObject.getIterations()) } - get iterationsExpr(): Expression { return wrapJoinPoint(this._javaObject.getIterationsExpr()) } - get kind(): "for" | "while" | "dowhile" | "foreach" { return wrapJoinPoint(this._javaObject.getKind()) } - set kind(value: string) { this._javaObject.setKind(unwrapJoinPoint(value)); } - get nestedLevel(): number { return wrapJoinPoint(this._javaObject.getNestedLevel()) } - get rank(): number[] { return wrapJoinPoint(this._javaObject.getRank()) } - /** - * The statement of the loop step - */ - get step(): Statement { return wrapJoinPoint(this._javaObject.getStep()) } - /** - * The statement of the loop step - */ - set step(value: string) { this._javaObject.setStep(unwrapJoinPoint(value)); } - /** - * The expression of the iteration step - */ - get stepValue(): string { return wrapJoinPoint(this._javaObject.getStepValue()) } - /** - * Tests whether the loops are interchangeable. This is a conservative test. + * The instructions that are associated with this case in the source code. This does not represent what instructions are actually executed (e.g., if a case does not have a break, does not show instructions of the next case) */ - isInterchangeable(otherLoop: Loop): boolean { return wrapJoinPoint(this._javaObject.isInterchangeable(unwrapJoinPoint(otherLoop))); } + get instructions(): Statement[] { return wrapJoinPoint(this._javaObject.instructions()) } + get isDefault(): boolean { return wrapJoinPoint(this._javaObject.isDefault()) } /** - * Interchanges two for loops, if possible + * True if this case does not contain instructions (i.e., it is directly above another case), false otherwise */ - interchange(otherLoop: Loop): void { return wrapJoinPoint(this._javaObject.interchange(unwrapJoinPoint(otherLoop))); } + get isEmpty(): boolean { return wrapJoinPoint(this._javaObject.isEmpty()) } /** - * Sets the body of the loop + * The case statement that comes after this case, or undefined if there are no more case statements */ - setBody(body: Scope): void { return wrapJoinPoint(this._javaObject.setBody(unwrapJoinPoint(body))); } + get nextCase(): Case { return wrapJoinPoint(this._javaObject.nextCase()) } /** - * Sets the conditional statement of the loop. Works with loops of kind 'for' + * The first statement that is not a case that will be executed by this case statement */ - setCond(condCode: string): void { return wrapJoinPoint(this._javaObject.setCond(unwrapJoinPoint(condCode))); } + get nextInstruction(): Statement { return wrapJoinPoint(this._javaObject.nextInstruction()) } /** - * Changes the operator of a canonical condition, if possible. Supported operators: lt, le, gt, ge + * The values that the case statement will match. It can return zero (e.g., 'default:'), one (e.g., 'case 1:') or two (e.g., 'case 2...4:') expressions, depending on the format of the case */ - setCondRelation(operator: Relation): void { return wrapJoinPoint(this._javaObject.setCondRelation(unwrapJoinPoint(operator))); } + get values(): Expression[] { return wrapJoinPoint(this._javaObject.values()) } +} + +export class Default extends SwitchCase { /** - * Sets the end value of the loop. Works with loops of kind 'for' + * @internal */ - setEndValue(initCode: string): void { return wrapJoinPoint(this._javaObject.setEndValue(unwrapJoinPoint(initCode))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; +} + +export class DeclStmt extends Statement { /** - * Sets the init statement of the loop + * @internal */ - setInit(initCode: string): void { return wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(initCode))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * Sets the init value of the loop. Works with loops of kind 'for' + * The declarations in this statement */ - setInitValue(initCode: string): void { return wrapJoinPoint(this._javaObject.setInitValue(unwrapJoinPoint(initCode))); } + get decls(): Decl[] { return wrapJoinPoint(this._javaObject.decls()) } +} + +export class ExprStmt extends Statement { /** - * Sets the attribute 'isParallel' of the loop + * @internal */ - setIsParallel(isParallel: boolean): void { return wrapJoinPoint(this._javaObject.setIsParallel(unwrapJoinPoint(isParallel))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * Sets the kind of the loop + * The expression join point associated to this exprStmt */ - setKind(kind: string): void { return wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(kind))); } + get expr(): Expression { return wrapJoinPoint(this._javaObject.expr()) } +} + +export class GotoStmt extends Statement { /** - * Sets the step statement of the loop. Works with loops of kind 'for' + * @internal */ - setStep(stepCode: string): void { return wrapJoinPoint(this._javaObject.setStep(unwrapJoinPoint(stepCode))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get label(): LabelDecl { return wrapJoinPoint(this._javaObject.label()) } + set label(value: LabelDecl) { this._javaObject.setLabel(unwrapJoinPoint(value)); } /** - * Applies loop tiling to this loop. + * Sets the label of the goto */ - tile(blockSize: string, reference: Statement, useTernary: boolean = true): Statement { return wrapJoinPoint(this._javaObject.tile(unwrapJoinPoint(blockSize), unwrapJoinPoint(reference), unwrapJoinPoint(useTernary))); } + setLabel(label: LabelDecl): void { return wrapJoinPoint(this._javaObject.setLabel(unwrapJoinPoint(label))); } } - /** - * Special pragma that can be used to mark scopes (e.g., #pragma lara marker loop1) - */ -export class Marker extends Pragma { +export class LabelStmt extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "id", + name: null, }; + get decl(): LabelDecl { return wrapJoinPoint(this._javaObject.decl()) } + set decl(value: LabelDecl) { this._javaObject.setDecl(unwrapJoinPoint(value)); } /** - * A scope, associated with this marker + * Sets the label of the label statement */ - get contents(): Joinpoint { return wrapJoinPoint(this._javaObject.getContents()) } - get id(): string { return wrapJoinPoint(this._javaObject.getId()) } + setDecl(label: LabelDecl): void { return wrapJoinPoint(this._javaObject.setDecl(unwrapJoinPoint(label))); } } -export class MemberCall extends Call { +export class EmptyStmt extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", + name: null, }; - get base(): Expression { return wrapJoinPoint(this._javaObject.getBase()) } - get rootBase(): Expression { return wrapJoinPoint(this._javaObject.getRootBase()) } } +export class Continue extends Statement { /** - * Represents a C++ class method declaration or definition + * @internal */ -export class Method extends FunctionJp { + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; +} + +export class Break extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", + name: null, }; - get record(): Class { return wrapJoinPoint(this._javaObject.getRecord()) } /** - * Removes the of the method + * The enclosing statement related to this break. It should be either a loop or a switch statement. */ - removeRecord(): void { return wrapJoinPoint(this._javaObject.removeRecord()); } + get enclosingStmt(): Statement { return wrapJoinPoint(this._javaObject.enclosingStmt()) } } - /** - * Represents an OpenMP pragma (e.g., #pragma omp parallel) - */ -export class Omp extends Pragma { +export class AsmStmt extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "kind", + name: null, }; + get clobbers(): string[] { return wrapJoinPoint(this._javaObject.clobbers()) } + get isSimple(): boolean { return wrapJoinPoint(this._javaObject.isSimple()) } + get isVolatile(): boolean { return wrapJoinPoint(this._javaObject.isVolatile()) } +} + +export class Expression extends Joinpoint { /** - * The names of the kinds of all clauses in the pragma, or empty array if no clause is defined + * @internal */ - get clauseKinds(): string[] { return wrapJoinPoint(this._javaObject.getClauseKinds()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * An integer expression, or undefined if no 'collapse' clause is defined + * A 'decl' join point that represents the declaration associated with this expression, or undefined if there is none */ - get collapse(): string { return wrapJoinPoint(this._javaObject.getCollapse()) } + get decl(): Decl { return wrapJoinPoint(this._javaObject.decl()) } /** - * An integer expression, or undefined if no 'collapse' clause is defined + * Returns a cast joinpoint if this expression has an associated implicit cast, undefined otherwise */ - set collapse(value: string | number) { this._javaObject.setCollapse(unwrapJoinPoint(value)); } + get implicitCast(): Cast { return wrapJoinPoint(this._javaObject.implicitCast()) } /** - * The variable names of all copyin clauses, or empty array if no copyin clause is defined + * True if the expression is part of an argument of a function call */ - get copyin(): string[] { return wrapJoinPoint(this._javaObject.getCopyin()) } + get isFunctionArgument(): boolean { return wrapJoinPoint(this._javaObject.isFunctionArgument()) } + get use(): ExpressionUse { return wrapJoinPoint(this._javaObject.use()) } /** - * The variable names of all copyin clauses, or empty array if no copyin clause is defined + * A 'vardecl' join point that represents the variable declaration associated with this expression, or undefined if there is none */ - set copyin(value: string[]) { this._javaObject.setCopyin(unwrapJoinPoint(value)); } + get vardecl(): Vardecl { return wrapJoinPoint(this._javaObject.vardecl()) } +} + +export class Call extends Expression { /** - * One of 'shared' or 'none', or undefined if no 'default' clause is defined + * @internal */ - get default(): string { return wrapJoinPoint(this._javaObject.getDefault()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; /** - * One of 'shared' or 'none', or undefined if no 'default' clause is defined + * An alias for 'args' + * + * @deprecated */ - set default(value: string) { this._javaObject.setDefault(unwrapJoinPoint(value)); } + get argList(): Expression[] { return wrapJoinPoint(this._javaObject.argList()) } /** - * The variable names of all firstprivate clauses, or empty array if no firstprivate clause is defined + * An array with the arguments of the call */ - get firstprivate(): string[] { return wrapJoinPoint(this._javaObject.getFirstprivate()) } + get args(): Expression[] { return wrapJoinPoint(this._javaObject.args()) } /** - * The variable names of all firstprivate clauses, or empty array if no firstprivate clause is defined + * A 'function' join point that represents the function of the call that was found, it can return either an implementation or a function prototype; 'undefined' if no declaration was found */ - set firstprivate(value: string[]) { this._javaObject.setFirstprivate(unwrapJoinPoint(value)); } + get declaration(): FunctionJp { return wrapJoinPoint(this._javaObject.declaration()) } /** - * The kind of the directive + * A 'function' join point that represents the function definition of the call; 'undefined' if no definition was found */ - get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } + get definition(): FunctionJp { return wrapJoinPoint(this._javaObject.definition()) } /** - * The kind of the directive + * A function join point that represents the 'raw' function of the call (e.g. if this is a call to a templated function, returns a declaration representing the template specialization, instead of the original function) */ - set kind(value: string) { this._javaObject.setKind(unwrapJoinPoint(value)); } + get directCallee(): FunctionJp { return wrapJoinPoint(this._javaObject.directCallee()) } /** - * The variable names of all lastprivate clauses, or empty array if no lastprivate clause is defined + * A function join point associated with this call. If a definition is present, it is given priority over returning a declaration. If only declarations are present, returns a declaration */ - get lastprivate(): string[] { return wrapJoinPoint(this._javaObject.getLastprivate()) } + get function(): FunctionJp { return wrapJoinPoint(this._javaObject.function()) } /** - * The variable names of all lastprivate clauses, or empty array if no lastprivate clause is defined + * The function type of the call, which includes the return type and the types of the parameters */ - set lastprivate(value: string[]) { this._javaObject.setLastprivate(unwrapJoinPoint(value)); } + get functionType(): FunctionType { return wrapJoinPoint(this._javaObject.functionType()) } + get isMemberAccess(): boolean { return wrapJoinPoint(this._javaObject.isMemberAccess()) } + get isStmtCall(): boolean { return wrapJoinPoint(this._javaObject.isStmtCall()) } + get memberAccess(): MemberAccess { return wrapJoinPoint(this._javaObject.memberAccess()) } + get memberNames(): string[] { return wrapJoinPoint(this._javaObject.memberNames()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } + set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } + get numArgs(): number { return wrapJoinPoint(this._javaObject.numArgs()) } /** - * An integer expression, or undefined if no 'num_threads' clause is defined + * The return type of the call */ - get numThreads(): string { return wrapJoinPoint(this._javaObject.getNumThreads()) } + get returnType(): Type { return wrapJoinPoint(this._javaObject.returnType()) } /** - * An integer expression, or undefined if no 'num_threads' clause is defined + * Similar to $function.signature, but if no function decl could be found (e.g., function from system include), returns a signature based on just the name of the function */ - set numThreads(value: string) { this._javaObject.setNumThreads(unwrapJoinPoint(value)); } + get signature(): string { return wrapJoinPoint(this._javaObject.signature()) } /** - * An integer expression, or undefined if no 'ordered' clause with a parameter is defined + * Adds an argument at the end of the call, creating an expression using the given code and type. If a type is not provided, a dummy type is used */ - get ordered(): string { return wrapJoinPoint(this._javaObject.getOrdered()) } + addArg(argCode: string, type?: Type): void; /** - * An integer expression, or undefined if no 'ordered' clause with a parameter is defined + * Adds an argument at the end of the call, creating a literal 'type' from the type string */ - set ordered(value: string) { this._javaObject.setOrdered(unwrapJoinPoint(value)); } + addArg(arg: string, type: string): void; /** - * The variable names of all private clauses, or empty array if no private clause is defined + * Adds an argument at the end of the call, creating an expression using the given code and type. If a type is not provided, a dummy type is used */ - get private(): string[] { return wrapJoinPoint(this._javaObject.getPrivate()) } + addArg(p1: string, p2?: Type | string): void { return wrapJoinPoint(this._javaObject.addArg(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + getArg(index: number): Expression { return wrapJoinPoint(this._javaObject.getArg(unwrapJoinPoint(index))); } /** - * The variable names of all private clauses, or empty array if no private clause is defined + * Tries to inline this call */ - set private(value: string[]) { this._javaObject.setPrivate(unwrapJoinPoint(value)); } + inline(): boolean { return wrapJoinPoint(this._javaObject.inline()); } + setArg(index: number, expr: Expression): void { return wrapJoinPoint(this._javaObject.setArg(unwrapJoinPoint(index), unwrapJoinPoint(expr))); } + setArgFromString(index: number, expr: string): void { return wrapJoinPoint(this._javaObject.setArgFromString(unwrapJoinPoint(index), unwrapJoinPoint(expr))); } /** - * One of 'master', 'close' or 'spread', or undefined if no 'proc_bind' clause is defined + * Changes the name of the call */ - get procBind(): string { return wrapJoinPoint(this._javaObject.getProcBind()) } + setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } /** - * One of 'master', 'close' or 'spread', or undefined if no 'proc_bind' clause is defined + * Wraps this call with a possibly new wrapping function */ - set procBind(value: string) { this._javaObject.setProcBind(unwrapJoinPoint(value)); } + wrap(name: string): void { return wrapJoinPoint(this._javaObject.wrap(unwrapJoinPoint(name))); } +} + +export class MemberCall extends Call { /** - * The reduction kinds in the reductions clauses of the this pragma, or empty array if no reduction is defined + * @internal */ - get reductionKinds(): string[] { return wrapJoinPoint(this._javaObject.getReductionKinds()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; + get base(): Expression { return wrapJoinPoint(this._javaObject.base()) } + get rootBase(): Expression { return wrapJoinPoint(this._javaObject.rootBase()) } +} + +export class CudaKernelCall extends Call { /** - * An integer expression, or undefined if no 'schedule' clause with chunk size is defined + * @internal */ - get scheduleChunkSize(): string { return wrapJoinPoint(this._javaObject.getScheduleChunkSize()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; + get config(): Expression[] { return wrapJoinPoint(this._javaObject.config()) } + set config(value: Expression[]) { this._javaObject.setConfig(unwrapJoinPoint(value)); } + setConfig(args: Expression[]): void { return wrapJoinPoint(this._javaObject.setConfig(unwrapJoinPoint(args))); } + setConfigFromStrings(args: string[]): void { return wrapJoinPoint(this._javaObject.setConfigFromStrings(unwrapJoinPoint(args))); } +} + +export class Op extends Expression { /** - * An integer expression, or undefined if no 'schedule' clause with chunk size is defined + * @internal */ - set scheduleChunkSize(value: string | number) { this._javaObject.setScheduleChunkSize(unwrapJoinPoint(value)); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get isBitwise(): boolean { return wrapJoinPoint(this._javaObject.isBitwise()) } /** - * One of 'static', 'dynamic', 'guided', 'auto' or 'runtime', or undefined if no 'schedule' clause is defined + * The kind of the operator. If it is a binary operator, can be one of: ptr_mem_d, ptr_mem_i, mul, div, rem, add, sub, shl, shr, cmp, lt, gt, le, ge, eq, ne, and, xor, or, l_and, l_or, assign, mul_assign, div_assign, rem_assign, add_assign, sub_assign, shl_assign, shr_assign, and_assign, xor_assign, or_assign, comma. If it is a unary operator, can be one of: post_inc, post_dec, pre_inc, pre_dec, addr_of, deref, plus, minus, not, l_not, real, imag, extension, cowait. If it is a ternary operator, the value will be 'ternary' */ - get scheduleKind(): string { return wrapJoinPoint(this._javaObject.getScheduleKind()) } + get kind(): OpKind { return wrapJoinPoint(this._javaObject.kind()) } + get operator(): string { return wrapJoinPoint(this._javaObject.operator()) } +} + +export class BinaryOp extends Op { /** - * One of 'static', 'dynamic', 'guided', 'auto' or 'runtime', or undefined if no 'schedule' clause is defined + * @internal */ - set scheduleKind(value: string) { this._javaObject.setScheduleKind(unwrapJoinPoint(value)); } - /** - * A list with possible values of 'monotonic', 'nonmonotonic' or 'simd', or undefined if no 'schedule' clause with modifiers is defined + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get isAssignment(): boolean { return wrapJoinPoint(this._javaObject.isAssignment()) } + get left(): Expression { return wrapJoinPoint(this._javaObject.left()) } + set left(value: Expression) { this._javaObject.setLeft(unwrapJoinPoint(value)); } + get right(): Expression { return wrapJoinPoint(this._javaObject.right()) } + set right(value: Expression) { this._javaObject.setRight(unwrapJoinPoint(value)); } + setLeft(left: Expression): void { return wrapJoinPoint(this._javaObject.setLeft(unwrapJoinPoint(left))); } + setRight(right: Expression): void { return wrapJoinPoint(this._javaObject.setRight(unwrapJoinPoint(right))); } +} + +export class UnaryOp extends Op { + /** + * @internal */ - get scheduleModifiers(): string[] { return wrapJoinPoint(this._javaObject.getScheduleModifiers()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get isPointerDeref(): boolean { return wrapJoinPoint(this._javaObject.isPointerDeref()) } + get operand(): Expression { return wrapJoinPoint(this._javaObject.operand()) } +} + +export class TernaryOp extends Op { /** - * A list with possible values of 'monotonic', 'nonmonotonic' or 'simd', or undefined if no 'schedule' clause with modifiers is defined + * @internal */ - set scheduleModifiers(value: string[]) { this._javaObject.setScheduleModifiers(unwrapJoinPoint(value)); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get cond(): Expression { return wrapJoinPoint(this._javaObject.cond()) } + get falseExpr(): Expression { return wrapJoinPoint(this._javaObject.falseExpr()) } + get trueExpr(): Expression { return wrapJoinPoint(this._javaObject.trueExpr()) } +} + +export class NewExpr extends Expression { /** - * The variable names of all shared clauses, or empty array if no shared clause is defined + * @internal */ - get shared(): string[] { return wrapJoinPoint(this._javaObject.getShared()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; +} + +export class DeleteExpr extends Expression { /** - * The variable names of all shared clauses, or empty array if no shared clause is defined + * @internal */ - set shared(value: string[]) { this._javaObject.setShared(unwrapJoinPoint(value)); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; +} + /** - * The variable names for the given reduction kind, or empty array if no reduction of that kind is defined + * A reference to a variable */ - getReduction(kind: string): string[] { return wrapJoinPoint(this._javaObject.getReduction(unwrapJoinPoint(kind))); } +export class Varref extends Expression { /** - * True if the directive has at least one clause of the given clause kind, false otherwise + * @internal */ - hasClause(clauseName: string): boolean { return wrapJoinPoint(this._javaObject.hasClause(unwrapJoinPoint(clauseName))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; + get declaration(): Declarator { return wrapJoinPoint(this._javaObject.declaration()) } /** - * True if it is legal to use the given clause kind in this directive, false otherwise + * True if this variable reference has a MS-style property, false otherwise */ - isClauseLegal(clauseName: string): boolean { return wrapJoinPoint(this._javaObject.isClauseLegal(unwrapJoinPoint(clauseName))); } + get hasProperty(): boolean { return wrapJoinPoint(this._javaObject.hasProperty()) } /** - * Removes any clause of the given kind from the OpenMP pragma + * True if this varref represents a function call */ - removeClause(clauseKind: string): void { return wrapJoinPoint(this._javaObject.removeClause(unwrapJoinPoint(clauseKind))); } + get isFunctionCall(): boolean { return wrapJoinPoint(this._javaObject.isFunctionCall()) } + get kind(): string { return wrapJoinPoint(this._javaObject.kind()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } + set name(value: string) { this._javaObject.setName(unwrapJoinPoint(value)); } /** - * Sets the value of the collapse clause of an OpenMP pragma + * If this variable reference has a MS-style property, returns the property name. Returns undefined otherwise */ - setCollapse(newExpr: string): void; + get property(): string { return wrapJoinPoint(this._javaObject.property()) } /** - * Sets the value of the collapse clause of an OpenMP pragma + * Expression from where the attribute 'use' is calculated. In certain cases (e.g., array access, pointer dereference) the 'use' attribute is not calculated on the node itself, but on an ancestor of the node. This attribute returns that node */ - setCollapse(newExpr: number): void; + get useExpr(): Expression { return wrapJoinPoint(this._javaObject.useExpr()) } + setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } +} + +export class Cast extends Expression { /** - * Sets the value of the collapse clause of an OpenMP pragma + * @internal */ - setCollapse(p1: string | number): void { return wrapJoinPoint(this._javaObject.setCollapse(unwrapJoinPoint(p1))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get fromType(): Type { return wrapJoinPoint(this._javaObject.fromType()) } /** - * Sets the variables of a copyin clause of an OpenMP pragma + * @deprecated Use expr.implicitCast instead */ - setCopyin(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setCopyin(unwrapJoinPoint(newVariables))); } + get isImplicitCast(): boolean { return wrapJoinPoint(this._javaObject.isImplicitCast()) } + get subExpr(): Expression { return wrapJoinPoint(this._javaObject.subExpr()) } + get toType(): Type { return wrapJoinPoint(this._javaObject.toType()) } +} + +export class ParenExpr extends Expression { /** - * Sets the value of the default clause of an OpenMP pragma + * @internal */ - setDefault(newDefault: string): void { return wrapJoinPoint(this._javaObject.setDefault(unwrapJoinPoint(newDefault))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * Sets the variables of a firstprivate clause of an OpenMP pragma + * Returns the expression inside this parenthesis expression */ - setFirstprivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setFirstprivate(unwrapJoinPoint(newVariables))); } + get subExpr(): Expression { return wrapJoinPoint(this._javaObject.subExpr()) } +} + +export class ArrayAccess extends Expression { /** - * Sets the directive kind of the OpenMP pragma. Any unsupported clauses will be discarded + * @internal */ - setKind(directiveKind: string): void { return wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(directiveKind))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * Sets the variables of a lastprivate clause of an OpenMP pragma + * Expression representing the variable of the array access (can be a varref, memberAccess...) */ - setLastprivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setLastprivate(unwrapJoinPoint(newVariables))); } + get arrayVar(): Expression { return wrapJoinPoint(this._javaObject.arrayVar()) } /** - * Sets the value of the num_threads clause of an OpenMP pragma + * If the array access is done over a variable, returns the name of the variable. Equivalent to $arrayAccess.arrayVar.name */ - setNumThreads(newExpr: string): void { return wrapJoinPoint(this._javaObject.setNumThreads(unwrapJoinPoint(newExpr))); } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } /** - * Sets the value of the ordered clause of an OpenMP pragma + * The number of subscripts of this array access */ - setOrdered(parameters?: string): void { return wrapJoinPoint(this._javaObject.setOrdered(unwrapJoinPoint(parameters))); } + get numSubscripts(): number { return wrapJoinPoint(this._javaObject.numSubscripts()) } /** - * Sets the variables of a private clause of an OpenMP pragma + * A view of the current arrayAccess without the last subscript, or undefined if this arrayAccess only has one subscript */ - setPrivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setPrivate(unwrapJoinPoint(newVariables))); } + get parentAccess(): ArrayAccess { return wrapJoinPoint(this._javaObject.parentAccess()) } /** - * Sets the value of the proc_bind clause of an OpenMP pragma + * Expression of the array access subscript */ - setProcBind(newBind: string): void { return wrapJoinPoint(this._javaObject.setProcBind(unwrapJoinPoint(newBind))); } + get subscript(): Expression[] { return wrapJoinPoint(this._javaObject.subscript()) } +} + +export class MemberAccess extends Expression { /** - * Sets the variables for a given kind of a reduction clause of an OpenMP pragma + * @internal */ - setReduction(kind: string, newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setReduction(unwrapJoinPoint(kind), unwrapJoinPoint(newVariables))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * Sets the value of the chunck size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception + * True if this is a member access that uses arrow (i.e., foo->bar), false if uses dot (i.e., foo.bar) */ - setScheduleChunkSize(chunkSize: string): void; + get arrow(): boolean { return wrapJoinPoint(this._javaObject.arrow()) } /** - * Sets the value of the chunck size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception + * True if this is a member access that uses arrow (i.e., foo->bar), false if uses dot (i.e., foo.bar) */ - setScheduleChunkSize(chunkSize: number): void; + set arrow(value: boolean) { this._javaObject.setArrow(unwrapJoinPoint(value)); } /** - * Sets the value of the chunck size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception + * Expression of the base of this member access */ - setScheduleChunkSize(p1: string | number): void { return wrapJoinPoint(this._javaObject.setScheduleChunkSize(unwrapJoinPoint(p1))); } + get base(): Expression { return wrapJoinPoint(this._javaObject.base()) } + get memberChain(): Expression[] { return wrapJoinPoint(this._javaObject.memberChain()) } + get memberChainNames(): string[] { return wrapJoinPoint(this._javaObject.memberChainNames()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } + setArrow(isArrow: boolean): void { return wrapJoinPoint(this._javaObject.setArrow(unwrapJoinPoint(isArrow))); } +} + +export class UnaryExprOrType extends Expression { /** - * Sets the value of the schedule clause of an OpenMP pragma + * @internal */ - setScheduleKind(scheduleKind: string): void { return wrapJoinPoint(this._javaObject.setScheduleKind(unwrapJoinPoint(scheduleKind))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get argExpr(): Expression { return wrapJoinPoint(this._javaObject.argExpr()) } + get argType(): Type { return wrapJoinPoint(this._javaObject.argType()) } + set argType(value: Type) { this._javaObject.setArgType(unwrapJoinPoint(value)); } + get hasArgExpr(): boolean { return wrapJoinPoint(this._javaObject.hasArgExpr()) } + get hasTypeExpr(): boolean { return wrapJoinPoint(this._javaObject.hasTypeExpr()) } + get kind(): string { return wrapJoinPoint(this._javaObject.kind()) } + setArgType(argType: Type): void { return wrapJoinPoint(this._javaObject.setArgType(unwrapJoinPoint(argType))); } +} + +export class This extends Expression { /** - * Sets the value of the modifiers in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception + * @internal */ - setScheduleModifiers(modifiers: string[]): void { return wrapJoinPoint(this._javaObject.setScheduleModifiers(unwrapJoinPoint(modifiers))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; +} + +export class Literal extends Expression { /** - * Sets the variables of a shared clause of an OpenMP pragma + * @internal */ - setShared(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setShared(unwrapJoinPoint(newVariables))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; } -export class ParenType extends Type { +export class IntLiteral extends Literal { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get innerType(): Type { return wrapJoinPoint(this._javaObject.getInnerType()) } - set innerType(value: Type) { this._javaObject.setInnerType(unwrapJoinPoint(value)); } + get value(): number { return wrapJoinPoint(this._javaObject.value()) } +} + +export class FloatLiteral extends Literal { /** - * Sets the inner type of this paren type + * @internal */ - setInnerType(innerType: Type): void { return wrapJoinPoint(this._javaObject.setInnerType(unwrapJoinPoint(innerType))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get value(): number { return wrapJoinPoint(this._javaObject.value()) } } -export class PointerType extends Type { +export class BoolLiteral extends Literal { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get pointee(): Type { return wrapJoinPoint(this._javaObject.getPointee()) } - set pointee(value: Type) { this._javaObject.setPointee(unwrapJoinPoint(value)); } + get value(): boolean { return wrapJoinPoint(this._javaObject.value()) } +} + +export class InitList extends Expression { /** - * Number of pointer levels from this pointer + * @internal */ - get pointerLevels(): number { return wrapJoinPoint(this._javaObject.getPointerLevels()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * Sets the pointee type of this pointer type + * [May be undefined] If this initializer list initializes an array with more elements than there are initializers in the list, specifies an expression to be used for value initialization of the rest of the elements */ - setPointee(pointeeType: Type): void { return wrapJoinPoint(this._javaObject.setPointee(unwrapJoinPoint(pointeeType))); } + get arrayFiller(): Expression { return wrapJoinPoint(this._javaObject.arrayFiller()) } } -export class QualType extends Type { +export class ImplicitValue extends Expression { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get qualifiers(): string[] { return wrapJoinPoint(this._javaObject.getQualifiers()) } - get unqualifiedType(): Type { return wrapJoinPoint(this._javaObject.getUnqualifiedType()) } } -export class ReturnStmt extends Statement { +export class Comment extends Joinpoint { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get returnExpr(): Expression { return wrapJoinPoint(this._javaObject.getReturnExpr()) } + get text(): string { return wrapJoinPoint(this._javaObject.text()) } + set text(value: string) { this._javaObject.setText(unwrapJoinPoint(value)); } + setText(text: string): void { return wrapJoinPoint(this._javaObject.setText(unwrapJoinPoint(text))); } } +export class CilkFor extends Loop { /** - * Represents a group of statements + * @internal */ -export class Scope extends Statement { + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "kind", + }; +} + +export class CilkSync extends Statement { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; +} + +export class CilkSpawn extends Call { /** - * Returns the descendant statements of this scope, excluding other scopes, loops, ifs and wrapper statements + * @internal */ - get allStmts(): Statement[] { return wrapJoinPoint(this._javaObject.getAllStmts()) } - get firstStmt(): Statement { return wrapJoinPoint(this._javaObject.getFirstStmt()) } - get lastStmt(): Statement { return wrapJoinPoint(this._javaObject.getLastStmt()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: "name", + }; +} + +export class Attribute extends Joinpoint { /** - * True if the scope does not have curly braces + * @internal */ - get naked(): boolean { return wrapJoinPoint(this._javaObject.getNaked()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get kind(): string { return wrapJoinPoint(this._javaObject.kind()) } +} + +export class Type extends Joinpoint { /** - * True if the scope does not have curly braces + * @internal */ - set naked(value: boolean) { this._javaObject.setNaked(unwrapJoinPoint(value)); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get arrayDims(): number[] { return wrapJoinPoint(this._javaObject.arrayDims()) } + get arraySize(): number { return wrapJoinPoint(this._javaObject.arraySize()) } + get constant(): boolean { return wrapJoinPoint(this._javaObject.constant()) } /** - * The statement that owns the scope (e.g., function, loop...) + * Single-step desugar. Returns the type itself if it does not have sugar */ - get owner(): Joinpoint { return wrapJoinPoint(this._javaObject.getOwner()) } + get desugar(): Type { return wrapJoinPoint(this._javaObject.desugar()) } /** - * Returns the direct (children) statements of this scope + * Single-step desugar. Returns the type itself if it does not have sugar */ - get stmts(): Statement[] { return wrapJoinPoint(this._javaObject.getStmts()) } + set desugar(value: Type) { this._javaObject.setDesugar(unwrapJoinPoint(value)); } /** - * The number of statements in the scope, including the statements inside the declaration and bodies of structures such as ifs and loops, and not considering comments and pragmas. If flat is true, does not consider the statements inside structures such as ifs and loops (e.g., a loop counts as one statement) + * Completely desugars the type */ - getNumStatements(flat: boolean = false): number { return wrapJoinPoint(this._javaObject.getNumStatements(unwrapJoinPoint(flat))); } + get desugarAll(): Type { return wrapJoinPoint(this._javaObject.desugarAll()) } /** - * Adds a new local variable to this scope + * A tree representation of the fields of this type */ - addLocal(name: string, type: Joinpoint, initValue?: string): Joinpoint { return wrapJoinPoint(this._javaObject.addLocal(unwrapJoinPoint(name), unwrapJoinPoint(type), unwrapJoinPoint(initValue))); } + get fieldTree(): string { return wrapJoinPoint(this._javaObject.fieldTree()) } + get hasSugar(): boolean { return wrapJoinPoint(this._javaObject.hasSugar()) } + get hasTemplateArgs(): boolean { return wrapJoinPoint(this._javaObject.hasTemplateArgs()) } + get isArray(): boolean { return wrapJoinPoint(this._javaObject.isArray()) } /** - * CFG tester + * True if this is a type declared with the 'auto' keyword */ - cfg(): string { return wrapJoinPoint(this._javaObject.cfg()); } + get isAuto(): boolean { return wrapJoinPoint(this._javaObject.isAuto()) } + get isBuiltin(): boolean { return wrapJoinPoint(this._javaObject.isBuiltin()) } + get isPointer(): boolean { return wrapJoinPoint(this._javaObject.isPointer()) } + get isTopLevel(): boolean { return wrapJoinPoint(this._javaObject.isTopLevel()) } + get kind(): string { return wrapJoinPoint(this._javaObject.kind()) } /** - * Clears the contents of this scope (untested) + * Ignores certain types (e.g., DecayedType) */ - clear(): void { return wrapJoinPoint(this._javaObject.clear()); } + get normalize(): Type { return wrapJoinPoint(this._javaObject.normalize()) } + get templateArgsStrings(): string[] { return wrapJoinPoint(this._javaObject.templateArgsStrings()) } + get templateArgsTypes(): Type[] { return wrapJoinPoint(this._javaObject.templateArgsTypes()) } + set templateArgsTypes(value: Type[]) { this._javaObject.setTemplateArgsTypes(unwrapJoinPoint(value)); } /** - * DFG tester + * Maps names of join point fields that represent type join points, to their respective values */ - dfg(): string { return wrapJoinPoint(this._javaObject.dfg()); } - insertBegin(node: Joinpoint): Joinpoint; - insertBegin(code: string): Joinpoint; - insertBegin(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertBegin(unwrapJoinPoint(p1))); } - insertEnd(node: Joinpoint): Joinpoint; - insertEnd(code: string): Joinpoint; - insertEnd(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertEnd(unwrapJoinPoint(p1))); } + get typeFields(): Record { return wrapJoinPoint(this._javaObject.typeFields()) } /** - * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node + * If the type encapsulates another type, returns the encapsulated type */ - insertReturn(code: Joinpoint): Joinpoint; + get unwrap(): Type { return wrapJoinPoint(this._javaObject.unwrap()) } /** - * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node + * Returns a new node based on this type with the qualifier const */ - insertReturn(code: string): Joinpoint; + asConst(): Type { return wrapJoinPoint(this._javaObject.asConst()); } /** - * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node + * Sets the desugared type of this type */ - insertReturn(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); } + setDesugar(desugaredType: Type): void { return wrapJoinPoint(this._javaObject.setDesugar(unwrapJoinPoint(desugaredType))); } /** - * Sets the 'naked' status of a scope (a scope is naked if it does not have curly braces) + * Sets the template argument types of a template type */ - setNaked(isNaked: boolean): void { return wrapJoinPoint(this._javaObject.setNaked(unwrapJoinPoint(isNaked))); } + setTemplateArgsTypes(templateArgTypes: Type[]): void { return wrapJoinPoint(this._javaObject.setTemplateArgsTypes(unwrapJoinPoint(templateArgTypes))); } + /** + * Sets a single template argument type of a template type + */ + setTemplateArgType(index: number, templateArgType: Type): void { return wrapJoinPoint(this._javaObject.setTemplateArgType(unwrapJoinPoint(index), unwrapJoinPoint(templateArgType))); } + /** + * Changes a single occurrence of a type field that has the current value with new value. Returns true if there was a change + */ + setTypeFieldByValueRecursive(currentValue: object, newValue: object): boolean { return wrapJoinPoint(this._javaObject.setTypeFieldByValueRecursive(unwrapJoinPoint(currentValue), unwrapJoinPoint(newValue))); } + /** + * Replaces an underlying type of this instance with new type, if it matches the old type + */ + setUnderlyingType(oldValue: Type, newValue: Type): Type { return wrapJoinPoint(this._javaObject.setUnderlyingType(unwrapJoinPoint(oldValue), unwrapJoinPoint(newValue))); } } -export class TagType extends Type { +export class PointerType extends Type { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; + get pointee(): Type { return wrapJoinPoint(this._javaObject.pointee()) } + set pointee(value: Type) { this._javaObject.setPointee(unwrapJoinPoint(value)); } /** - * A 'decl' join point that represents the declaration of this tag type + * Number of pointer levels from this pointer + */ + get pointerLevels(): number { return wrapJoinPoint(this._javaObject.pointerLevels()) } + /** + * Sets the pointee type of this pointer type */ - get decl(): Decl { return wrapJoinPoint(this._javaObject.getDecl()) } - get name(): string { return wrapJoinPoint(this._javaObject.getName()) } + setPointee(pointeeType: Type): void { return wrapJoinPoint(this._javaObject.setPointee(unwrapJoinPoint(pointeeType))); } } -export class TemplateSpecializationType extends Type { +export class ArrayType extends Type { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get args(): string[] { return wrapJoinPoint(this._javaObject.getArgs()) } - get firstArgType(): Type { return wrapJoinPoint(this._javaObject.getFirstArgType()) } - get numArgs(): number { return wrapJoinPoint(this._javaObject.getNumArgs()) } - get templateName(): string { return wrapJoinPoint(this._javaObject.getTemplateName()) } -} - + get elementType(): Type { return wrapJoinPoint(this._javaObject.elementType()) } + set elementType(value: Type) { this._javaObject.setElementType(unwrapJoinPoint(value)); } /** - * Declaration of a typedef-name via the 'typedef' type specifier + * Sets the element type of the array */ -export class TypedefDecl extends TypedefNameDecl { + setElementType(arrayElementType: Type): void { return wrapJoinPoint(this._javaObject.setElementType(unwrapJoinPoint(arrayElementType))); } +} + +export class AdjustedType extends Type { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", + name: null, }; -} - /** - * Represents a variable declaration or definition + * The type that is being adjusted */ -export class Vardecl extends Declarator { + get originalType(): Type { return wrapJoinPoint(this._javaObject.originalType()) } +} + +export class VariableArrayType extends ArrayType { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", + name: null, }; + get sizeExpr(): Expression { return wrapJoinPoint(this._javaObject.sizeExpr()) } + set sizeExpr(value: Expression) { this._javaObject.setSizeExpr(unwrapJoinPoint(value)); } /** - * The vardecl corresponding to the actual definition. For global variables, returns the vardecl of the file where it is actually defined (instead of the vardecl that defines an external link to the variable) + * Sets the size expression of this variable array type */ - get definition(): Vardecl { return wrapJoinPoint(this._javaObject.getDefinition()) } + setSizeExpr(sizeExpr: Expression): void { return wrapJoinPoint(this._javaObject.setSizeExpr(unwrapJoinPoint(sizeExpr))); } +} + +export class IncompleteArrayType extends ArrayType { /** - * True, if vardecl has an initialization value + * @internal */ - get hasInit(): boolean { return wrapJoinPoint(this._javaObject.getHasInit()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; +} + +export class TagType extends Type { /** - * If vardecl has an initialization value, returns an expression with that value + * @internal */ - get init(): Expression { return wrapJoinPoint(this._javaObject.getInit()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; /** - * If vardecl has an initialization value, returns an expression with that value + * A 'decl' join point that represents the declaration of this tag type */ - set init(value: Expression | string) { this._javaObject.setInit(unwrapJoinPoint(value)); } + get decl(): Decl { return wrapJoinPoint(this._javaObject.decl()) } + get name(): string { return wrapJoinPoint(this._javaObject.name()) } +} + +export class EnumType extends TagType { /** - * The initialization style of this vardecl, which can be no_init, cinit, callinit, listinit + * @internal */ - get initStyle(): string { return wrapJoinPoint(this._javaObject.getInitStyle()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get integerType(): Type { return wrapJoinPoint(this._javaObject.integerType()) } +} + +export class TemplateSpecializationType extends Type { /** - * True, if this variable does not have local storage. This includes all global variables as well as static variables declared within a function. + * @internal */ - get isGlobal(): boolean { return wrapJoinPoint(this._javaObject.getIsGlobal()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get args(): string[] { return wrapJoinPoint(this._javaObject.args()) } + get firstArgType(): Type { return wrapJoinPoint(this._javaObject.firstArgType()) } + get numArgs(): number { return wrapJoinPoint(this._javaObject.numArgs()) } + get templateName(): string { return wrapJoinPoint(this._javaObject.templateName()) } +} + +export class FunctionType extends Type { /** - * True, if vardecl is a function parameter + * @internal */ - get isParam(): boolean { return wrapJoinPoint(this._javaObject.getIsParam()) } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get paramTypes(): Type[] { return wrapJoinPoint(this._javaObject.paramTypes()) } + get returnType(): Type { return wrapJoinPoint(this._javaObject.returnType()) } + set returnType(value: Type) { this._javaObject.setReturnType(unwrapJoinPoint(value)); } /** - * Storage class specifier, which can be none, extern, static, __private_extern__, auto, register + * Sets the type of a parameter of the FunctionType. Be careful that if you directly change the type of a parameter and the function type is associated with a function declaration, this change will not be reflected in the function. If you want to change the type of a parameter of a function declaration, use function.setParamType */ - get storageClass(): StorageClass { return wrapJoinPoint(this._javaObject.getStorageClass()) } + setParamType(index: number, newType: Type): void { return wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); } /** - * Storage class specifier, which can be none, extern, static, __private_extern__, auto, register + * Sets the return type of the FunctionType */ - set storageClass(value: StorageClass) { this._javaObject.setStorageClass(unwrapJoinPoint(value)); } + setReturnType(newType: Type): void { return wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(newType))); } +} + +export class QualType extends Type { /** - * If vardecl already has an initialization, removes it. + * @internal */ - removeInit(removeConst: boolean = true): void { return wrapJoinPoint(this._javaObject.removeInit(unwrapJoinPoint(removeConst))); } + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get qualifiers(): string[] { return wrapJoinPoint(this._javaObject.qualifiers()) } + get unqualifiedType(): Type { return wrapJoinPoint(this._javaObject.unqualifiedType()) } +} + +export class BuiltinType extends Type { /** - * Sets the given expression as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization + * @internal */ - setInit(init: Expression): void; + static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { + name: null, + }; + get builtinKind(): string { return wrapJoinPoint(this._javaObject.builtinKind()) } /** - * Converts the given string to a literal expression and sets it as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization + * True, if it is a floating type (e.g., float, double) */ - setInit(init: string): void; + get isFloat(): boolean { return wrapJoinPoint(this._javaObject.isFloat()) } /** - * Sets the given expression as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization + * True, if it is an integer type */ - setInit(p1: Expression | string): void { return wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(p1))); } + get isInteger(): boolean { return wrapJoinPoint(this._javaObject.isInteger()) } /** - * Sets the storage class specifier, which can be none, extern, static, __private_extern__, autovardecl + * True, if it is a signed type */ - setStorageClass(storageClass: StorageClass): void { return wrapJoinPoint(this._javaObject.setStorageClass(unwrapJoinPoint(storageClass))); } + get isSigned(): boolean { return wrapJoinPoint(this._javaObject.isSigned()) } /** - * Creates a new varref based on this vardecl + * True, if it is an unsigned type */ - varref(): Varref { return wrapJoinPoint(this._javaObject.varref()); } + get isUnsigned(): boolean { return wrapJoinPoint(this._javaObject.isUnsigned()) } + /** + * True, if it is a void type + */ + get isVoid(): boolean { return wrapJoinPoint(this._javaObject.isVoid()) } } -export class VariableArrayType extends ArrayType { +export class ParenType extends Type { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get sizeExpr(): Expression { return wrapJoinPoint(this._javaObject.getSizeExpr()) } - set sizeExpr(value: Expression) { this._javaObject.setSizeExpr(unwrapJoinPoint(value)); } + get innerType(): Type { return wrapJoinPoint(this._javaObject.innerType()) } + set innerType(value: Type) { this._javaObject.setInnerType(unwrapJoinPoint(value)); } /** - * Sets the size expression of this variable array type + * Sets the inner type of this paren type */ - setSizeExpr(sizeExpr: Expression): void { return wrapJoinPoint(this._javaObject.setSizeExpr(unwrapJoinPoint(sizeExpr))); } + setInnerType(innerType: Type): void { return wrapJoinPoint(this._javaObject.setInnerType(unwrapJoinPoint(innerType))); } } -export class Body extends Scope { +export class UndefinedType extends Type { /** * @internal */ @@ -2804,143 +2764,260 @@ export class Body extends Scope { }; } -export class CilkFor extends Loop { /** - * @internal + * Represents a type that was referred to using an elaborated type keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, or both. This type is used to keep track of a type name as written in the source code, including tag keywords and any nested-name-specifiers. The type itself is always 'sugar', used to express what was written in the source code but containing no additional semantic information. */ - static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "kind", - }; -} - -export class EnumType extends TagType { +export class ElaboratedType extends Type { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; - get integerType(): Type { return wrapJoinPoint(this._javaObject.getIntegerType()) } + /** + * The keyword of this elaborated type, if present. Can be one of: struct, interface, union, class, enum, typename + */ + get keyword(): string { return wrapJoinPoint(this._javaObject.keyword()) } + /** + * The type that is being prefixed with the qualifier + */ + get namedType(): Type { return wrapJoinPoint(this._javaObject.namedType()) } + /** + * The qualifier of this elaborated type, if present (e.g., A::) + */ + get qualifier(): string { return wrapJoinPoint(this._javaObject.qualifier()) } } -export class Param extends Vardecl { +export class TypedefType extends Type { /** * @internal */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { - name: "name", + name: null, }; -} - -export enum StorageClass { - AUTO = "auto", - EXTERN = "extern", - NONE = "none", - PRIVATE_EXTERN = "private_extern", - REGISTER = "register", - STATIC = "static", -} - -export enum Relation { - EQ = "eq", - GE = "ge", - GT = "gt", - LE = "le", - LT = "lt", - NE = "ne", -} + /** + * The typedef declaration associated with this typedef type + */ + get decl(): TypedefNameDecl { return wrapJoinPoint(this._javaObject.decl()) } + /** + * The type being aliased + */ + get underlyingType(): Type { return wrapJoinPoint(this._javaObject.underlyingType()) } +} + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +export const StorageClass = { + NONE: "NONE", + AUTO: "AUTO", + EXTERN: "EXTERN", + PRIVATE_EXTERN: "PRIVATE_EXTERN", + REGISTER: "REGISTER", + STATIC: "STATIC", +} as const; +export type StorageClass = typeof StorageClass[keyof typeof StorageClass]; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +export const Relation = { + LE: "LE", + LT: "LT", + GE: "GE", + GT: "GT", + EQ: "EQ", + NE: "NE", +} as const; +export type Relation = typeof Relation[keyof typeof Relation]; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +export const LoopKind = { + for: "for", + while: "while", + dowhile: "dowhile", + foreach: "foreach", +} as const; +export type LoopKind = typeof LoopKind[keyof typeof LoopKind]; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +export const ExpressionUse = { + read: "read", + write: "write", + readwrite: "readwrite", +} as const; +export type ExpressionUse = typeof ExpressionUse[keyof typeof ExpressionUse]; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +export const OpKind = { + ptr_mem_d: "ptr_mem_d", + ptr_mem_i: "ptr_mem_i", + mul: "mul", + div: "div", + rem: "rem", + add: "add", + sub: "sub", + shl: "shl", + shr: "shr", + cmp: "cmp", + lt: "lt", + gt: "gt", + le: "le", + ge: "ge", + eq: "eq", + ne: "ne", + and: "and", + xor: "xor", + or: "or", + l_and: "l_and", + l_or: "l_or", + assign: "assign", + mul_assign: "mul_assign", + div_assign: "div_assign", + rem_assign: "rem_assign", + add_assign: "add_assign", + sub_assign: "sub_assign", + shl_assign: "shl_assign", + shr_assign: "shr_assign", + and_assign: "and_assign", + xor_assign: "xor_assign", + or_assign: "or_assign", + comma: "comma", + post_inc: "post_inc", + post_dec: "post_dec", + pre_inc: "pre_inc", + pre_dec: "pre_dec", + addr_of: "addr_of", + deref: "deref", + plus: "plus", + minus: "minus", + not: "not", + l_not: "l_not", + real: "real", + imag: "imag", + extension: "extension", + cowait: "cowait", + ternary: "ternary", +} as const; +export type OpKind = typeof OpKind[keyof typeof OpKind]; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +export const WrapperStatementKind = { + comment: "comment", + pragma: "pragma", +} as const; +export type WrapperStatementKind = typeof WrapperStatementKind[keyof typeof WrapperStatementKind]; const JoinpointMapper = { joinpoint: Joinpoint, - attribute: Attribute, - clavaException: ClavaException, - comment: Comment, - decl: Decl, empty: Empty, - expression: Expression, + program: Program, file: FileJp, - implicitValue: ImplicitValue, - include: Include, - initList: InitList, - literal: Literal, - memberAccess: MemberAccess, + decl: Decl, namedDecl: NamedDecl, - newExpr: NewExpr, - op: Op, - parenExpr: ParenExpr, - pragma: Pragma, - program: Program, + declarator: Declarator, + include: Include, record: RecordJp, - statement: Statement, + field: Field, struct: Struct, - switch: Switch, - switchCase: SwitchCase, - tag: Tag, - ternaryOp: TernaryOp, - this: This, - type: Type, + class: Class, + vardecl: Vardecl, typedefNameDecl: TypedefNameDecl, - typedefType: TypedefType, - unaryExprOrType: UnaryExprOrType, - unaryOp: UnaryOp, - undefinedType: UndefinedType, - varref: Varref, - wrapperStmt: WrapperStmt, + typedefDecl: TypedefDecl, + enumDecl: EnumDecl, + enumeratorDecl: EnumeratorDecl, + labelDecl: LabelDecl, accessSpecifier: AccessSpecifier, - adjustedType: AdjustedType, - arrayAccess: ArrayAccess, - arrayType: ArrayType, - asmStmt: AsmStmt, - binaryOp: BinaryOp, - boolLiteral: BoolLiteral, - break: Break, - builtinType: BuiltinType, - call: Call, + param: Param, + function: FunctionJp, + method: Method, + pragma: Pragma, + marker: Marker, + tag: Tag, + omp: Omp, + statement: Statement, + scope: Scope, + body: Body, + loop: Loop, + if: If, + wrapperStmt: WrapperStmt, + returnStmt: ReturnStmt, + switch: Switch, + switchCase: SwitchCase, case: Case, - cast: Cast, - cilkSpawn: CilkSpawn, - cilkSync: CilkSync, - class: Class, - continue: Continue, - cudaKernelCall: CudaKernelCall, - declStmt: DeclStmt, - declarator: Declarator, default: Default, - deleteExpr: DeleteExpr, - elaboratedType: ElaboratedType, - emptyStmt: EmptyStmt, - enumDecl: EnumDecl, - enumeratorDecl: EnumeratorDecl, + declStmt: DeclStmt, exprStmt: ExprStmt, - field: Field, - floatLiteral: FloatLiteral, - function: FunctionJp, - functionType: FunctionType, gotoStmt: GotoStmt, - if: If, - incompleteArrayType: IncompleteArrayType, - intLiteral: IntLiteral, - labelDecl: LabelDecl, labelStmt: LabelStmt, - loop: Loop, - marker: Marker, + emptyStmt: EmptyStmt, + continue: Continue, + break: Break, + asmStmt: AsmStmt, + expression: Expression, + call: Call, memberCall: MemberCall, - method: Method, - omp: Omp, - parenType: ParenType, + cudaKernelCall: CudaKernelCall, + op: Op, + binaryOp: BinaryOp, + unaryOp: UnaryOp, + ternaryOp: TernaryOp, + newExpr: NewExpr, + deleteExpr: DeleteExpr, + varref: Varref, + cast: Cast, + parenExpr: ParenExpr, + arrayAccess: ArrayAccess, + memberAccess: MemberAccess, + unaryExprOrType: UnaryExprOrType, + This: This, + literal: Literal, + intLiteral: IntLiteral, + floatLiteral: FloatLiteral, + boolLiteral: BoolLiteral, + initList: InitList, + implicitValue: ImplicitValue, + comment: Comment, + cilkFor: CilkFor, + cilkSync: CilkSync, + cilkSpawn: CilkSpawn, + attribute: Attribute, + type: Type, pointerType: PointerType, - qualType: QualType, - returnStmt: ReturnStmt, - scope: Scope, - tagType: TagType, - templateSpecializationType: TemplateSpecializationType, - typedefDecl: TypedefDecl, - vardecl: Vardecl, + arrayType: ArrayType, + adjustedType: AdjustedType, variableArrayType: VariableArrayType, - body: Body, - cilkFor: CilkFor, + incompleteArrayType: IncompleteArrayType, + tagType: TagType, enumType: EnumType, - param: Param, + templateSpecializationType: TemplateSpecializationType, + functionType: FunctionType, + qualType: QualType, + builtinType: BuiltinType, + parenType: ParenType, + undefinedType: UndefinedType, + elaboratedType: ElaboratedType, + typedefType: TypedefType, }; let registered = false; diff --git a/Clava-JS/src-api/LegacyIntegrationTests - C.test.ts b/Clava-JS/api/LegacyIntegrationTests - C.test.ts similarity index 98% rename from Clava-JS/src-api/LegacyIntegrationTests - C.test.ts rename to Clava-JS/api/LegacyIntegrationTests - C.test.ts index e039f61c09..db3f36a05a 100644 --- a/Clava-JS/src-api/LegacyIntegrationTests - C.test.ts +++ b/Clava-JS/api/LegacyIntegrationTests - C.test.ts @@ -1,12 +1,12 @@ -import { ClavaLegacyTester } from "../jest/ClavaLegacyTester.js"; -import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import ClavaJavaTypes from "@specs-feup/clava/api/clava/ClavaJavaTypes.js"; +import { ClavaLegacyTester } from "../vitest/ClavaLegacyTester.ts"; +import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import ClavaJavaTypes from "./clava/ClavaJavaTypes.ts"; import path from "path"; const isWindows = process.platform === "win32"; const isMacOS = process.platform === "darwin"; -/* eslint-disable jest/expect-expect */ +/* oxlint-disable vitest/expect-expect */ describe("CTest", () => { function newTester() { return new ClavaLegacyTester( @@ -101,7 +101,7 @@ describe("CTest", () => { await newTester() .checkExpectedOutput(false) .test("InlineNasLu.js", "inline_nas_lu.c"); - }); + }, 10_000); it("InlineNasFt", async () => { await newTester() @@ -340,7 +340,7 @@ describe("CApiTest", () => { } await tester.test("InlinerTest.js", "inliner.c"); - }); + }, 15_000); it("StatementDecomposer", async () => { await newTester().test( diff --git a/Clava-JS/src-api/LegacyIntegrationTests - CXX.test.ts b/Clava-JS/api/LegacyIntegrationTests - CXX.test.ts similarity index 98% rename from Clava-JS/src-api/LegacyIntegrationTests - CXX.test.ts rename to Clava-JS/api/LegacyIntegrationTests - CXX.test.ts index 5473c3bc3a..1ffcb5fbf7 100644 --- a/Clava-JS/src-api/LegacyIntegrationTests - CXX.test.ts +++ b/Clava-JS/api/LegacyIntegrationTests - CXX.test.ts @@ -1,12 +1,12 @@ -import { ClavaLegacyTester } from "../jest/ClavaLegacyTester.js"; -import ClavaJavaTypes from "@specs-feup/clava/api/clava/ClavaJavaTypes.js"; -import JavaInterop from "@specs-feup/lara/api/lara/JavaInterop.js"; +import { ClavaLegacyTester } from "../vitest/ClavaLegacyTester.ts"; +import ClavaJavaTypes from "./clava/ClavaJavaTypes.ts"; +import JavaInterop from "@specs-feup/lara/api/lara/JavaInterop.ts"; import path from "path"; const isWindows = process.platform === "win32"; const isMacOS = process.platform === "darwin"; -/* eslint-disable jest/expect-expect */ +/* oxlint-disable vitest/expect-expect */ describe("CxxTest", () => { function newTester() { return new ClavaLegacyTester( diff --git a/Clava-JS/src-api/LegacyIntegrationTests - Issues.test.ts b/Clava-JS/api/LegacyIntegrationTests - Issues.test.ts similarity index 75% rename from Clava-JS/src-api/LegacyIntegrationTests - Issues.test.ts rename to Clava-JS/api/LegacyIntegrationTests - Issues.test.ts index 480a24262a..c4782a44ec 100644 --- a/Clava-JS/src-api/LegacyIntegrationTests - Issues.test.ts +++ b/Clava-JS/api/LegacyIntegrationTests - Issues.test.ts @@ -1,8 +1,8 @@ -import { ClavaLegacyTester } from "../jest/ClavaLegacyTester.js"; -import ClavaJavaTypes from "@specs-feup/clava/api/clava/ClavaJavaTypes.js"; +import { ClavaLegacyTester } from "../vitest/ClavaLegacyTester.ts"; +import ClavaJavaTypes from "./clava/ClavaJavaTypes.ts"; import path from "path"; -/* eslint-disable jest/expect-expect */ +/* oxlint-disable vitest/expect-expect */ describe("IssuesTest", () => { function newTester() { return new ClavaLegacyTester( diff --git a/Clava-JS/src-api/Query.test.ts b/Clava-JS/api/Query.test.ts similarity index 93% rename from Clava-JS/src-api/Query.test.ts rename to Clava-JS/api/Query.test.ts index 477308a338..f937f5a1fb 100644 --- a/Clava-JS/src-api/Query.test.ts +++ b/Clava-JS/api/Query.test.ts @@ -1,6 +1,6 @@ -import { registerSourceCode } from "@specs-feup/lara/jest/jestHelpers.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { FunctionJp, Loop } from "./Joinpoints.js"; +import { registerSourceCode } from "@specs-feup/lara/vitest/weaverTestHelpers.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { FunctionJp, Loop } from "./Joinpoints.ts"; const code = `void query_loop() { for(int i=0; i<10; i++) { diff --git a/Clava-JS/api/SourceLocations.test.ts b/Clava-JS/api/SourceLocations.test.ts new file mode 100644 index 0000000000..c805d530c0 --- /dev/null +++ b/Clava-JS/api/SourceLocations.test.ts @@ -0,0 +1,94 @@ +import { registerSourceCode } from "@specs-feup/lara/vitest/weaverTestHelpers.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { Joinpoint, Vardecl } from "./Joinpoints.ts"; + +const code = `#define VALUE 7 +#define CAT_IMPL(left, right) left ## right +#define CAT(left, right) CAT_IMPL(left, right) +#define DECL(name) int name = VALUE; + +DECL(CAT(macro_, value)) +int ordinary = 0; +int foobar = 1; +int pasted_reference = CAT(foo, bar); + +namespace std { +using uint8_t = unsigned char; +template class vector; +} // namespace std + +template > +class Holder {}; +`; + +describe("source locations", () => { + registerSourceCode(code); + + it("uses real file coordinates for ordinary and macro-expanded nodes", () => { + const ordinary = Query.search(Vardecl, "ordinary").first(); + const macro = Query.search(Vardecl, "macro_value").first(); + + expect(ordinary).toBeDefined(); + expect(macro).toBeDefined(); + + if (ordinary === undefined || macro === undefined) { + return; + } + + expect(ordinary.isMacro).toBe(false); + expect(ordinary.filename).toBe("dummyFile.cpp"); + expect(ordinary.filepath).toMatch(/dummyFile\.cpp$/); + expect(ordinary.line).toBe(7); + expect(ordinary.endLine).toBe(7); + expect(ordinary.location).not.toContain(""); + + expect(macro.isMacro).toBe(true); + expect(macro.filename).toBe("dummyFile.cpp"); + expect(macro.filepath).toMatch(/dummyFile\.cpp$/); + expect(macro.line).toBe(6); + expect(macro.endLine).toBe(6); + expect(macro.column).toBe(1); + expect(macro.endColumn).toBe(24); + expect(macro.location).not.toContain(""); + + expect(macro.init.isMacro).toBe(true); + expect(macro.init.filename).toBe("dummyFile.cpp"); + expect(macro.init.line).toBe(6); + expect(macro.init.location).not.toContain(""); + + const pastedReference = Query.search(Vardecl, "pasted_reference").first(); + expect(pastedReference).toBeDefined(); + if (pastedReference === undefined) { + return; + } + + expect(pastedReference.init.isMacro).toBe(true); + expect(pastedReference.init.filename).toBe("dummyFile.cpp"); + expect(pastedReference.init.line).toBe(9); + expect(pastedReference.init.column).toBe(24); + expect(pastedReference.init.endColumn).toBe(36); + expect(pastedReference.init.location).not.toContain(""); + }); + + it("does not treat Clang's split closing angle brackets as macros", () => { + const declarations = Query.search("decl").get() as Joinpoint[]; + const templateParameter = declarations.find( + (joinpoint) => joinpoint.astName === "TemplateTypeParmDecl" + && joinpoint.line === 16 + ); + + expect(templateParameter).toBeDefined(); + if (templateParameter === undefined) { + return; + } + + expect(templateParameter.isMacro).toBe(false); + expect(templateParameter.filename).toBe("dummyFile.cpp"); + expect(templateParameter.filepath).toMatch(/dummyFile\.cpp$/); + expect(templateParameter.line).toBe(16); + expect(templateParameter.endLine).toBe(16); + expect(templateParameter.column).toBe(11); + expect(templateParameter.endColumn).toBe(54); + expect(templateParameter.location).not.toContain(""); + }); +}); diff --git a/Clava-JS/src-api/clava/Clava.ts b/Clava-JS/api/clava/Clava.ts similarity index 93% rename from Clava-JS/src-api/clava/Clava.ts rename to Clava-JS/api/clava/Clava.ts index d6e402ca5d..3f03b49626 100644 --- a/Clava-JS/src-api/clava/Clava.ts +++ b/Clava-JS/api/clava/Clava.ts @@ -1,13 +1,12 @@ -import { wrapJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js"; -import Io from "@specs-feup/lara/api/lara/Io.js"; -import JavaInterop from "@specs-feup/lara/api/lara/JavaInterop.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import Weaver from "@specs-feup/lara/api/weaver/Weaver.js"; -import WeaverOptions from "@specs-feup/lara/api/weaver/WeaverOptions.js"; -import { FileJp, Include, Joinpoint, Program } from "../Joinpoints.js"; -import ClavaJavaTypes from "./ClavaJavaTypes.js"; -import ClavaDataStore from "./util/ClavaDataStore.js"; +import { wrapJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.ts"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import Weaver from "@specs-feup/lara/api/weaver/Weaver.ts"; +import WeaverOptions from "@specs-feup/lara/api/weaver/WeaverOptions.ts"; +import { FileJp, Include, Joinpoint, Program } from "../Joinpoints.ts"; +import ClavaJavaTypes from "./ClavaJavaTypes.ts"; +import ClavaDataStore from "./util/ClavaDataStore.ts"; export default class Clava { /** diff --git a/Clava-JS/src-api/clava/ClavaCode.ts b/Clava-JS/api/clava/ClavaCode.ts similarity index 95% rename from Clava-JS/src-api/clava/ClavaCode.ts rename to Clava-JS/api/clava/ClavaCode.ts index d50230427c..38b6190e59 100644 --- a/Clava-JS/src-api/clava/ClavaCode.ts +++ b/Clava-JS/api/clava/ClavaCode.ts @@ -1,7 +1,7 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { FileJp, FunctionJp, @@ -11,8 +11,8 @@ import { Statement, StorageClass, Vardecl, -} from "../Joinpoints.js"; -import Clava from "./Clava.js"; +} from "../Joinpoints.ts"; +import Clava from "./Clava.ts"; /** * Utility methods related with the source code. diff --git a/Clava-JS/src-api/clava/ClavaJavaTypes.ts b/Clava-JS/api/clava/ClavaJavaTypes.ts similarity index 92% rename from Clava-JS/src-api/clava/ClavaJavaTypes.ts rename to Clava-JS/api/clava/ClavaJavaTypes.ts index 8e0ade6355..e617cf3b43 100644 --- a/Clava-JS/src-api/clava/ClavaJavaTypes.ts +++ b/Clava-JS/api/clava/ClavaJavaTypes.ts @@ -1,10 +1,10 @@ import JavaTypes, { - JavaClasses, -} from "@specs-feup/lara/api/lara/util/JavaTypes.js"; + type JavaClasses, +} from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; -// eslint-disable-next-line @typescript-eslint/no-namespace +// oxlint-disable-next-line typescript/no-namespace export namespace ClavaJavaClasses { - /* eslint-disable @typescript-eslint/no-empty-object-type */ + /* oxlint-disable typescript/no-empty-object-type */ export interface ClavaNodes extends JavaClasses.JavaClass {} export interface ClavaNode extends JavaClasses.JavaClass {} export interface CxxJoinpoints extends JavaClasses.JavaClass {} @@ -19,7 +19,7 @@ export namespace ClavaJavaClasses { export interface CxxWeaverOption extends JavaClasses.JavaClass {} export interface ClavaOptions extends JavaClasses.JavaClass {} export interface CodeParser extends JavaClasses.JavaClass {} - /* eslint-enable @typescript-eslint/no-empty-object-type */ + /* oxlint-enable typescript/no-empty-object-type */ } /** diff --git a/Clava-JS/src-api/clava/ClavaJoinPoints.test.ts b/Clava-JS/api/clava/ClavaJoinPoints.test.ts similarity index 65% rename from Clava-JS/src-api/clava/ClavaJoinPoints.test.ts rename to Clava-JS/api/clava/ClavaJoinPoints.test.ts index f570a5edac..ae34056103 100644 --- a/Clava-JS/src-api/clava/ClavaJoinPoints.test.ts +++ b/Clava-JS/api/clava/ClavaJoinPoints.test.ts @@ -1,7 +1,7 @@ -import { registerSourceCode } from "@specs-feup/lara/jest/jestHelpers.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { ExprStmt } from "../Joinpoints.js"; -import ClavaJoinPoints from "./ClavaJoinPoints.js"; +import { registerSourceCode } from "@specs-feup/lara/vitest/weaverTestHelpers.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { ExprStmt } from "../Joinpoints.ts"; +import ClavaJoinPoints from "./ClavaJoinPoints.ts"; const code = `int main() { int a = 0, b = 0; diff --git a/Clava-JS/src-api/clava/ClavaJoinPoints.ts b/Clava-JS/api/clava/ClavaJoinPoints.ts similarity index 98% rename from Clava-JS/src-api/clava/ClavaJoinPoints.ts rename to Clava-JS/api/clava/ClavaJoinPoints.ts index a514ad85f2..0b4193b9a8 100644 --- a/Clava-JS/src-api/clava/ClavaJoinPoints.ts +++ b/Clava-JS/api/clava/ClavaJoinPoints.ts @@ -1,16 +1,16 @@ import { unwrapJoinPoint, wrapJoinPoint, -} from "@specs-feup/lara/api/LaraJoinPoint.js"; +} from "@specs-feup/lara/api/LaraJoinPoint.ts"; import { arrayFromArgs, flattenArgsArray, -} from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import * as Joinpoints from "../Joinpoints.js"; -import Clava from "./Clava.js"; -import ClavaJavaTypes from "./ClavaJavaTypes.js"; -import Weaver from "@specs-feup/lara/api/weaver/Weaver.js"; +} from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import * as Joinpoints from "../Joinpoints.ts"; +import Clava from "./Clava.ts"; +import ClavaJavaTypes from "./ClavaJavaTypes.ts"; +import Weaver from "@specs-feup/lara/api/weaver/Weaver.ts"; /** * Utility methods related with the creation of new join points. @@ -486,7 +486,7 @@ export default class ClavaJoinPoints { } static compoundAssign( - op: string, + op: Joinpoints.OpKind, $leftHand: Joinpoints.Expression, $rightHand: Joinpoints.Expression ): Joinpoints.BinaryOp { @@ -536,7 +536,7 @@ export default class ClavaJoinPoints { * @param $type - The return type of the operator. If a string, it is converted to a literal type. */ static binaryOp( - op: string, + op: Joinpoints.OpKind, $left: Joinpoints.Expression | string, $right: Joinpoints.Expression | string, $type: Joinpoints.Type | string = "int" @@ -570,7 +570,7 @@ export default class ClavaJoinPoints { * @param $type - The return type of the operator. If undefined, tries to infer the correct type based on the type of the $expr (inference might not be implemented for all operators). */ static unaryOp( - op: string, + op: Joinpoints.OpKind, $expr: Joinpoints.Expression, $type?: Joinpoints.Type | string ): Joinpoints.UnaryOp; @@ -582,12 +582,12 @@ export default class ClavaJoinPoints { * @param $type - The return type of the operator that will be converted to a literal type. */ static unaryOp( - op: string, + op: Joinpoints.OpKind, $expr: string, $type: Joinpoints.Type | string ): Joinpoints.UnaryOp; static unaryOp( - op: string, + op: Joinpoints.OpKind, $expr: Joinpoints.Expression | string, $type?: Joinpoints.Type | string ): Joinpoints.UnaryOp { @@ -1068,12 +1068,12 @@ export default class ClavaJoinPoints { */ static memberAccess( baseExpr: Joinpoints.Expression, - fieldName: String, + fieldName: string, fieldType: Joinpoints.Type ): Joinpoints.MemberAccess; static memberAccess( baseExpr: Joinpoints.Expression, - field: Joinpoints.Field | String, + field: Joinpoints.Field | string, fieldType?: Joinpoints.Type ): Joinpoints.MemberAccess { if (typeof field === "string") { diff --git a/Clava-JS/src-api/clava/ClavaType.ts b/Clava-JS/api/clava/ClavaType.ts similarity index 97% rename from Clava-JS/src-api/clava/ClavaType.ts rename to Clava-JS/api/clava/ClavaType.ts index 94a5b456f8..29783ace42 100644 --- a/Clava-JS/src-api/clava/ClavaType.ts +++ b/Clava-JS/api/clava/ClavaType.ts @@ -8,9 +8,9 @@ import { Type, VariableArrayType, Varref, -} from "../Joinpoints.js"; -import ClavaJoinPoints from "./ClavaJoinPoints.js"; -import ClavaJavaTypes from "./ClavaJavaTypes.js"; +} from "../Joinpoints.ts"; +import ClavaJoinPoints from "./ClavaJoinPoints.ts"; +import ClavaJavaTypes from "./ClavaJavaTypes.ts"; /** * Utility methods related with the type join points. diff --git a/Clava-JS/src-api/clava/Format.ts b/Clava-JS/api/clava/Format.ts similarity index 99% rename from Clava-JS/src-api/clava/Format.ts rename to Clava-JS/api/clava/Format.ts index a3793873d3..a8b4beede1 100644 --- a/Clava-JS/src-api/clava/Format.ts +++ b/Clava-JS/api/clava/Format.ts @@ -1,4 +1,4 @@ -import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.js"; +import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; export default class Format { static addPrefix(str: string, prefix: string): string { diff --git a/Clava-JS/src-api/clava/MathExtra.ts b/Clava-JS/api/clava/MathExtra.ts similarity index 94% rename from Clava-JS/src-api/clava/MathExtra.ts rename to Clava-JS/api/clava/MathExtra.ts index 4a2a69272c..371ac294a9 100644 --- a/Clava-JS/src-api/clava/MathExtra.ts +++ b/Clava-JS/api/clava/MathExtra.ts @@ -1,6 +1,6 @@ -import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import { Expression } from "../Joinpoints.js"; -import ClavaJavaTypes from "./ClavaJavaTypes.js"; +import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import { Expression } from "../Joinpoints.ts"; +import ClavaJavaTypes from "./ClavaJavaTypes.ts"; export default class MathExtra { /** diff --git a/Clava-JS/src-api/clava/analysis/Analyser.ts b/Clava-JS/api/clava/analysis/Analyser.ts similarity index 54% rename from Clava-JS/src-api/clava/analysis/Analyser.ts rename to Clava-JS/api/clava/analysis/Analyser.ts index b0b382413c..4cdfff7047 100644 --- a/Clava-JS/src-api/clava/analysis/Analyser.ts +++ b/Clava-JS/api/clava/analysis/Analyser.ts @@ -1,5 +1,5 @@ -import { Joinpoint } from "../../Joinpoints.js"; -import ResultList from "./ResultList.js"; +import { Joinpoint } from "../../Joinpoints.ts"; +import ResultList from "./ResultList.ts"; export default abstract class Analyser { abstract analyse($node?: Joinpoint): ResultList | undefined; diff --git a/Clava-JS/src-api/clava/analysis/AnalyserResult.test.ts b/Clava-JS/api/clava/analysis/AnalyserResult.test.ts similarity index 84% rename from Clava-JS/src-api/clava/analysis/AnalyserResult.test.ts rename to Clava-JS/api/clava/analysis/AnalyserResult.test.ts index 7effbf0216..990414af42 100644 --- a/Clava-JS/src-api/clava/analysis/AnalyserResult.test.ts +++ b/Clava-JS/api/clava/analysis/AnalyserResult.test.ts @@ -1,5 +1,5 @@ -import AnalyserResult from "./AnalyserResult.js"; -import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js"; +import AnalyserResult from "./AnalyserResult.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; describe("AnalyserResult", () => { describe("getName", () => { diff --git a/Clava-JS/src-api/clava/analysis/AnalyserResult.ts b/Clava-JS/api/clava/analysis/AnalyserResult.ts similarity index 87% rename from Clava-JS/src-api/clava/analysis/AnalyserResult.ts rename to Clava-JS/api/clava/analysis/AnalyserResult.ts index 7c8787bc5c..5219e1e09d 100644 --- a/Clava-JS/src-api/clava/analysis/AnalyserResult.ts +++ b/Clava-JS/api/clava/analysis/AnalyserResult.ts @@ -1,5 +1,5 @@ -import { Joinpoint } from "../../Joinpoints.js"; -import Fix from "./Fix.js"; +import { Joinpoint } from "../../Joinpoints.ts"; +import Fix from "./Fix.ts"; /** * Abstract class created as a model for every result of analyser diff --git a/Clava-JS/src-api/clava/analysis/CheckBasedAnalyser.ts b/Clava-JS/api/clava/analysis/CheckBasedAnalyser.ts similarity index 83% rename from Clava-JS/src-api/clava/analysis/CheckBasedAnalyser.ts rename to Clava-JS/api/clava/analysis/CheckBasedAnalyser.ts index 9020b4bbe8..98aa2bdd83 100644 --- a/Clava-JS/src-api/clava/analysis/CheckBasedAnalyser.ts +++ b/Clava-JS/api/clava/analysis/CheckBasedAnalyser.ts @@ -1,9 +1,9 @@ -import Analyser from "./Analyser.js"; -import Checker from "./Checker.js"; -import ResultFormatManager from "./ResultFormatManager.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { FileJp, Joinpoint, Program } from "../../Joinpoints.js"; -import AnalyserResult from "./AnalyserResult.js"; +import Analyser from "./Analyser.ts"; +import Checker from "./Checker.ts"; +import ResultFormatManager from "./ResultFormatManager.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { FileJp, Joinpoint, Program } from "../../Joinpoints.ts"; +import AnalyserResult from "./AnalyserResult.ts"; type T = Program | FileJp; diff --git a/Clava-JS/src-api/clava/analysis/CheckResult.ts b/Clava-JS/api/clava/analysis/CheckResult.ts similarity index 54% rename from Clava-JS/src-api/clava/analysis/CheckResult.ts rename to Clava-JS/api/clava/analysis/CheckResult.ts index 69af292a18..8125cd3f82 100644 --- a/Clava-JS/src-api/clava/analysis/CheckResult.ts +++ b/Clava-JS/api/clava/analysis/CheckResult.ts @@ -1,3 +1,3 @@ -import AnalyserResult from "./AnalyserResult.js"; +import AnalyserResult from "./AnalyserResult.ts"; export default class CheckResult extends AnalyserResult {} diff --git a/Clava-JS/src-api/clava/analysis/Checker.ts b/Clava-JS/api/clava/analysis/Checker.ts similarity index 70% rename from Clava-JS/src-api/clava/analysis/Checker.ts rename to Clava-JS/api/clava/analysis/Checker.ts index 05520bbb8a..2c3639b83d 100644 --- a/Clava-JS/src-api/clava/analysis/Checker.ts +++ b/Clava-JS/api/clava/analysis/Checker.ts @@ -1,5 +1,5 @@ -import { Joinpoint } from "../../Joinpoints.js"; -import AnalyserResult from "./AnalyserResult.js"; +import { Joinpoint } from "../../Joinpoints.ts"; +import AnalyserResult from "./AnalyserResult.ts"; export default abstract class Checker { name: string; diff --git a/Clava-JS/src-api/clava/analysis/Fix.ts b/Clava-JS/api/clava/analysis/Fix.ts similarity index 86% rename from Clava-JS/src-api/clava/analysis/Fix.ts rename to Clava-JS/api/clava/analysis/Fix.ts index e774d87768..0c1d44a2a5 100644 --- a/Clava-JS/src-api/clava/analysis/Fix.ts +++ b/Clava-JS/api/clava/analysis/Fix.ts @@ -1,4 +1,4 @@ -import { Joinpoint } from "../../Joinpoints.js"; +import { Joinpoint } from "../../Joinpoints.ts"; export default class Fix { private node: Joinpoint; diff --git a/Clava-JS/src-api/clava/analysis/MessageGenerator.ts b/Clava-JS/api/clava/analysis/MessageGenerator.ts similarity index 91% rename from Clava-JS/src-api/clava/analysis/MessageGenerator.ts rename to Clava-JS/api/clava/analysis/MessageGenerator.ts index 25e663a2b0..260b942fc8 100644 --- a/Clava-JS/src-api/clava/analysis/MessageGenerator.ts +++ b/Clava-JS/api/clava/analysis/MessageGenerator.ts @@ -1,7 +1,7 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import Clava from "../Clava.js"; -import AnalyserResult from "./AnalyserResult.js"; -import ResultList from "./ResultList.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import Clava from "../Clava.ts"; +import AnalyserResult from "./AnalyserResult.ts"; +import ResultList from "./ResultList.ts"; // Class sorting resultLists and generating an analysis report diff --git a/Clava-JS/src-api/clava/analysis/ResultFormatManager.ts b/Clava-JS/api/clava/analysis/ResultFormatManager.ts similarity index 84% rename from Clava-JS/src-api/clava/analysis/ResultFormatManager.ts rename to Clava-JS/api/clava/analysis/ResultFormatManager.ts index 4a620b3bbc..25db7976d4 100644 --- a/Clava-JS/src-api/clava/analysis/ResultFormatManager.ts +++ b/Clava-JS/api/clava/analysis/ResultFormatManager.ts @@ -1,6 +1,6 @@ -import { FileJp, Program } from "../../Joinpoints.js"; -import AnalyserResult from "./AnalyserResult.js"; -import ResultList from "./ResultList.js"; +import { FileJp, Program } from "../../Joinpoints.ts"; +import AnalyserResult from "./AnalyserResult.ts"; +import ResultList from "./ResultList.ts"; /** * Class to format the results from the analyser into a resultList diff --git a/Clava-JS/src-api/clava/analysis/ResultList.ts b/Clava-JS/api/clava/analysis/ResultList.ts similarity index 81% rename from Clava-JS/src-api/clava/analysis/ResultList.ts rename to Clava-JS/api/clava/analysis/ResultList.ts index 366a138c6a..7f59ed5bb7 100644 --- a/Clava-JS/src-api/clava/analysis/ResultList.ts +++ b/Clava-JS/api/clava/analysis/ResultList.ts @@ -1,4 +1,4 @@ -import AnalyserResult from "./AnalyserResult.js"; +import AnalyserResult from "./AnalyserResult.ts"; export default class ResultList { fileName: string; diff --git a/Clava-JS/src-api/clava/analysis/analysers/BoundsAnalyser.ts b/Clava-JS/api/clava/analysis/analysers/BoundsAnalyser.ts similarity index 93% rename from Clava-JS/src-api/clava/analysis/analysers/BoundsAnalyser.ts rename to Clava-JS/api/clava/analysis/analysers/BoundsAnalyser.ts index 9ab20fdf63..b7987b44bb 100644 --- a/Clava-JS/src-api/clava/analysis/analysers/BoundsAnalyser.ts +++ b/Clava-JS/api/clava/analysis/analysers/BoundsAnalyser.ts @@ -1,4 +1,4 @@ -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { ArrayAccess, ArrayType, @@ -6,10 +6,10 @@ import { FunctionJp, Program, Vardecl, -} from "../../../Joinpoints.js"; -import Analyser from "../Analyser.js"; -import ResultFormatManager from "../ResultFormatManager.js"; -import BoundsResult from "./BoundsResult.js"; +} from "../../../Joinpoints.ts"; +import Analyser from "../Analyser.ts"; +import ResultFormatManager from "../ResultFormatManager.ts"; +import BoundsResult from "./BoundsResult.ts"; type T = Program | FileJp; diff --git a/Clava-JS/src-api/clava/analysis/analysers/BoundsResult.ts b/Clava-JS/api/clava/analysis/analysers/BoundsResult.ts similarity index 83% rename from Clava-JS/src-api/clava/analysis/analysers/BoundsResult.ts rename to Clava-JS/api/clava/analysis/analysers/BoundsResult.ts index edab2f4c61..aeaacdc7cc 100644 --- a/Clava-JS/src-api/clava/analysis/analysers/BoundsResult.ts +++ b/Clava-JS/api/clava/analysis/analysers/BoundsResult.ts @@ -1,6 +1,6 @@ -import { Vardecl } from "../../../Joinpoints.js"; -import AnalyserResult from "../AnalyserResult.js"; -import Fix from "../Fix.js"; +import { Vardecl } from "../../../Joinpoints.ts"; +import AnalyserResult from "../AnalyserResult.ts"; +import Fix from "../Fix.ts"; export default class BoundsResult extends AnalyserResult { arrayName: string; diff --git a/Clava-JS/src-api/clava/analysis/analysers/DoubleFreeAnalyser.ts b/Clava-JS/api/clava/analysis/analysers/DoubleFreeAnalyser.ts similarity index 92% rename from Clava-JS/src-api/clava/analysis/analysers/DoubleFreeAnalyser.ts rename to Clava-JS/api/clava/analysis/analysers/DoubleFreeAnalyser.ts index 43fd4198a1..28f62b985f 100644 --- a/Clava-JS/src-api/clava/analysis/analysers/DoubleFreeAnalyser.ts +++ b/Clava-JS/api/clava/analysis/analysers/DoubleFreeAnalyser.ts @@ -1,4 +1,4 @@ -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { BinaryOp, Call, @@ -7,10 +7,10 @@ import { Joinpoint, Program, Vardecl, -} from "../../../Joinpoints.js"; -import Analyser from "../Analyser.js"; -import ResultFormatManager from "../ResultFormatManager.js"; -import DoubleFreeResult from "./DoubleFreeResult.js"; +} from "../../../Joinpoints.ts"; +import Analyser from "../Analyser.ts"; +import ResultFormatManager from "../ResultFormatManager.ts"; +import DoubleFreeResult from "./DoubleFreeResult.ts"; type T = Program | FileJp; diff --git a/Clava-JS/src-api/clava/analysis/analysers/DoubleFreeResult.ts b/Clava-JS/api/clava/analysis/analysers/DoubleFreeResult.ts similarity index 73% rename from Clava-JS/src-api/clava/analysis/analysers/DoubleFreeResult.ts rename to Clava-JS/api/clava/analysis/analysers/DoubleFreeResult.ts index 135627f00a..a5a80cf6a5 100644 --- a/Clava-JS/src-api/clava/analysis/analysers/DoubleFreeResult.ts +++ b/Clava-JS/api/clava/analysis/analysers/DoubleFreeResult.ts @@ -1,6 +1,6 @@ -import { Joinpoint } from "../../../Joinpoints.js"; -import AnalyserResult from "../AnalyserResult.js"; -import Fix from "../Fix.js"; +import { Joinpoint } from "../../../Joinpoints.ts"; +import AnalyserResult from "../AnalyserResult.ts"; +import Fix from "../Fix.ts"; export default class DoubleFreeResult extends AnalyserResult { ptrName: string; diff --git a/Clava-JS/src-api/clava/analysis/checkers/ChgrpChecker.ts b/Clava-JS/api/clava/analysis/checkers/ChgrpChecker.ts similarity index 80% rename from Clava-JS/src-api/clava/analysis/checkers/ChgrpChecker.ts rename to Clava-JS/api/clava/analysis/checkers/ChgrpChecker.ts index 9394c59004..f9e4bdfead 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/ChgrpChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/ChgrpChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of chgrp functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/ChmodChecker.ts b/Clava-JS/api/clava/analysis/checkers/ChmodChecker.ts similarity index 80% rename from Clava-JS/src-api/clava/analysis/checkers/ChmodChecker.ts rename to Clava-JS/api/clava/analysis/checkers/ChmodChecker.ts index ebac3efb3e..eb0b7ffc00 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/ChmodChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/ChmodChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of chmod functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/ChownChecker.ts b/Clava-JS/api/clava/analysis/checkers/ChownChecker.ts similarity index 80% rename from Clava-JS/src-api/clava/analysis/checkers/ChownChecker.ts rename to Clava-JS/api/clava/analysis/checkers/ChownChecker.ts index a66b095785..dd74d7eba0 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/ChownChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/ChownChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of chown functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/CinChecker.ts b/Clava-JS/api/clava/analysis/checkers/CinChecker.ts similarity index 80% rename from Clava-JS/src-api/clava/analysis/checkers/CinChecker.ts rename to Clava-JS/api/clava/analysis/checkers/CinChecker.ts index d7edb5b30a..1fc3ef1bb2 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/CinChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/CinChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; export default class CinChecker extends Checker { private advice = diff --git a/Clava-JS/src-api/clava/analysis/checkers/ExecChecker.ts b/Clava-JS/api/clava/analysis/checkers/ExecChecker.ts similarity index 82% rename from Clava-JS/src-api/clava/analysis/checkers/ExecChecker.ts rename to Clava-JS/api/clava/analysis/checkers/ExecChecker.ts index cf4aa2a542..b0dd2cca18 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/ExecChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/ExecChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of exec family functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/FprintfChecker.ts b/Clava-JS/api/clava/analysis/checkers/FprintfChecker.ts similarity index 80% rename from Clava-JS/src-api/clava/analysis/checkers/FprintfChecker.ts rename to Clava-JS/api/clava/analysis/checkers/FprintfChecker.ts index dcc200d23c..ae842ab983 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/FprintfChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/FprintfChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of fprintf functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/FscanfChecker.ts b/Clava-JS/api/clava/analysis/checkers/FscanfChecker.ts similarity index 79% rename from Clava-JS/src-api/clava/analysis/checkers/FscanfChecker.ts rename to Clava-JS/api/clava/analysis/checkers/FscanfChecker.ts index 775ecf88d1..49b0d72365 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/FscanfChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/FscanfChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of fscanf functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/GetsChecker.ts b/Clava-JS/api/clava/analysis/checkers/GetsChecker.ts similarity index 82% rename from Clava-JS/src-api/clava/analysis/checkers/GetsChecker.ts rename to Clava-JS/api/clava/analysis/checkers/GetsChecker.ts index 6488a8bc27..786188b982 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/GetsChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/GetsChecker.ts @@ -1,7 +1,7 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; -import Fix from "../Fix.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; +import Fix from "../Fix.ts"; /** * Check for the presence of gets functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/LambdaChecker.ts b/Clava-JS/api/clava/analysis/checkers/LambdaChecker.ts similarity index 81% rename from Clava-JS/src-api/clava/analysis/checkers/LambdaChecker.ts rename to Clava-JS/api/clava/analysis/checkers/LambdaChecker.ts index 6d8d55ffc7..ea4ae4ccf7 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/LambdaChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/LambdaChecker.ts @@ -1,6 +1,6 @@ -import { Joinpoint, Vardecl } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Joinpoint, Vardecl } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of lambda objects using capture by reference diff --git a/Clava-JS/src-api/clava/analysis/checkers/MemcpyChecker.ts b/Clava-JS/api/clava/analysis/checkers/MemcpyChecker.ts similarity index 78% rename from Clava-JS/src-api/clava/analysis/checkers/MemcpyChecker.ts rename to Clava-JS/api/clava/analysis/checkers/MemcpyChecker.ts index bcf849d9fa..c89eb8d043 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/MemcpyChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/MemcpyChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of memcpy functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/PrintfChecker.ts b/Clava-JS/api/clava/analysis/checkers/PrintfChecker.ts similarity index 79% rename from Clava-JS/src-api/clava/analysis/checkers/PrintfChecker.ts rename to Clava-JS/api/clava/analysis/checkers/PrintfChecker.ts index d42cf29c52..5cd270c866 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/PrintfChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/PrintfChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of printf functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/ScanfChecker.ts b/Clava-JS/api/clava/analysis/checkers/ScanfChecker.ts similarity index 81% rename from Clava-JS/src-api/clava/analysis/checkers/ScanfChecker.ts rename to Clava-JS/api/clava/analysis/checkers/ScanfChecker.ts index 69c8d38970..65c46d42bc 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/ScanfChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/ScanfChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of scanf functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/SprintfChecker.ts b/Clava-JS/api/clava/analysis/checkers/SprintfChecker.ts similarity index 87% rename from Clava-JS/src-api/clava/analysis/checkers/SprintfChecker.ts rename to Clava-JS/api/clava/analysis/checkers/SprintfChecker.ts index 0bed50093b..9607a8ddd1 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/SprintfChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/SprintfChecker.ts @@ -1,7 +1,7 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; -import Fix from "../Fix.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; +import Fix from "../Fix.ts"; /** * Check for the presence of sprintf functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/StrcatChecker.ts b/Clava-JS/api/clava/analysis/checkers/StrcatChecker.ts similarity index 83% rename from Clava-JS/src-api/clava/analysis/checkers/StrcatChecker.ts rename to Clava-JS/api/clava/analysis/checkers/StrcatChecker.ts index 10c9aea20c..0b75676a5c 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/StrcatChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/StrcatChecker.ts @@ -1,7 +1,7 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; -import Fix from "../Fix.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; +import Fix from "../Fix.ts"; /** * Check for the presence of strcat functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/StrcpyChecker.ts b/Clava-JS/api/clava/analysis/checkers/StrcpyChecker.ts similarity index 80% rename from Clava-JS/src-api/clava/analysis/checkers/StrcpyChecker.ts rename to Clava-JS/api/clava/analysis/checkers/StrcpyChecker.ts index 9c3aef5252..f21b6f2ecf 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/StrcpyChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/StrcpyChecker.ts @@ -1,9 +1,9 @@ -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; -import Fix from "../Fix.js"; -import { Joinpoint, Call } from "../../../Joinpoints.js"; -import AnalyserResult from "../AnalyserResult.js"; -import ClavaJoinPoints from "../../ClavaJoinPoints.js"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; +import Fix from "../Fix.ts"; +import { Joinpoint, Call } from "../../../Joinpoints.ts"; +import AnalyserResult from "../AnalyserResult.ts"; +import ClavaJoinPoints from "../../ClavaJoinPoints.ts"; /*Check for the presence of strcpy functions*/ diff --git a/Clava-JS/src-api/clava/analysis/checkers/SyslogChecker.ts b/Clava-JS/api/clava/analysis/checkers/SyslogChecker.ts similarity index 79% rename from Clava-JS/src-api/clava/analysis/checkers/SyslogChecker.ts rename to Clava-JS/api/clava/analysis/checkers/SyslogChecker.ts index d418e80a69..2859e8cc79 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/SyslogChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/SyslogChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of syslog functions diff --git a/Clava-JS/src-api/clava/analysis/checkers/SystemChecker.ts b/Clava-JS/api/clava/analysis/checkers/SystemChecker.ts similarity index 80% rename from Clava-JS/src-api/clava/analysis/checkers/SystemChecker.ts rename to Clava-JS/api/clava/analysis/checkers/SystemChecker.ts index 8fc727477d..16bd5b16fc 100644 --- a/Clava-JS/src-api/clava/analysis/checkers/SystemChecker.ts +++ b/Clava-JS/api/clava/analysis/checkers/SystemChecker.ts @@ -1,6 +1,6 @@ -import { Call, Joinpoint } from "../../../Joinpoints.js"; -import Checker from "../Checker.js"; -import CheckResult from "../CheckResult.js"; +import { Call, Joinpoint } from "../../../Joinpoints.ts"; +import Checker from "../Checker.ts"; +import CheckResult from "../CheckResult.ts"; /** * Check for the presence of system functions diff --git a/Clava-JS/src-api/clava/cmake/CMaker.ts b/Clava-JS/api/clava/cmake/CMaker.ts similarity index 95% rename from Clava-JS/src-api/clava/cmake/CMaker.ts rename to Clava-JS/api/clava/cmake/CMaker.ts index ee3a289716..142c61addf 100644 --- a/Clava-JS/src-api/clava/cmake/CMaker.ts +++ b/Clava-JS/api/clava/cmake/CMaker.ts @@ -1,18 +1,18 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import Platforms from "@specs-feup/lara/api/lara/Platforms.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import Platforms from "@specs-feup/lara/api/lara/Platforms.ts"; import { arrayFromArgs, debug, debugObject, -} from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import ProcessExecutor from "@specs-feup/lara/api/lara/util/ProcessExecutor.js"; -import { FileJp } from "../../Joinpoints.js"; -import Clava from "../Clava.js"; -import CMakerSources from "./CMakerSources.js"; -import CMakerUtils from "./CMakerUtils.js"; -import CMakeCompiler from "./compilers/CMakeCompiler.js"; -import BenchmarkCompilationEngine from "@specs-feup/lara/api/lara/benchmark/BenchmarkCompilationEngine.js"; +} from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import ProcessExecutor from "@specs-feup/lara/api/lara/util/ProcessExecutor.ts"; +import { FileJp } from "../../Joinpoints.ts"; +import Clava from "../Clava.ts"; +import CMakerSources from "./CMakerSources.ts"; +import CMakerUtils from "./CMakerUtils.ts"; +import CMakeCompiler from "./compilers/CMakeCompiler.ts"; +import BenchmarkCompilationEngine from "@specs-feup/lara/api/lara/benchmark/BenchmarkCompilationEngine.ts"; /** * Builds CMake configurations. diff --git a/Clava-JS/src-api/clava/cmake/CMakerSources.ts b/Clava-JS/api/clava/cmake/CMakerSources.ts similarity index 94% rename from Clava-JS/src-api/clava/cmake/CMakerSources.ts rename to Clava-JS/api/clava/cmake/CMakerSources.ts index b824a7c7ce..aa5ea4a490 100644 --- a/Clava-JS/src-api/clava/cmake/CMakerSources.ts +++ b/Clava-JS/api/clava/cmake/CMakerSources.ts @@ -1,8 +1,8 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import Clava from "../Clava.js"; -import CMakerUtils from "./CMakerUtils.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import Clava from "../Clava.ts"; +import CMakerUtils from "./CMakerUtils.ts"; /** * Contains CMaker sources diff --git a/Clava-JS/src-api/clava/cmake/CMakerUtils.ts b/Clava-JS/api/clava/cmake/CMakerUtils.ts similarity index 92% rename from Clava-JS/src-api/clava/cmake/CMakerUtils.ts rename to Clava-JS/api/clava/cmake/CMakerUtils.ts index eff7c88906..c6f21edade 100644 --- a/Clava-JS/src-api/clava/cmake/CMakerUtils.ts +++ b/Clava-JS/api/clava/cmake/CMakerUtils.ts @@ -1,6 +1,6 @@ -import ToolUtils from "@specs-feup/lara/api/lara/tool/ToolUtils.js"; -import CMakeCompiler from "./compilers/CMakeCompiler.js"; -import GenericCMakeCompiler from "./compilers/GenericCMakeCompiler.js"; +import ToolUtils from "@specs-feup/lara/api/lara/tool/ToolUtils.ts"; +import CMakeCompiler from "./compilers/CMakeCompiler.ts"; +import GenericCMakeCompiler from "./compilers/GenericCMakeCompiler.ts"; export default class CMakerUtils extends ToolUtils { private static compilerTable = { diff --git a/Clava-JS/src-api/clava/cmake/compilers/CMakeCompiler.ts b/Clava-JS/api/clava/cmake/compilers/CMakeCompiler.ts similarity index 100% rename from Clava-JS/src-api/clava/cmake/compilers/CMakeCompiler.ts rename to Clava-JS/api/clava/cmake/compilers/CMakeCompiler.ts diff --git a/Clava-JS/src-api/clava/cmake/compilers/GenericCMakeCompiler.ts b/Clava-JS/api/clava/cmake/compilers/GenericCMakeCompiler.ts similarity index 87% rename from Clava-JS/src-api/clava/cmake/compilers/GenericCMakeCompiler.ts rename to Clava-JS/api/clava/cmake/compilers/GenericCMakeCompiler.ts index 75d817f142..246ca1c289 100644 --- a/Clava-JS/src-api/clava/cmake/compilers/GenericCMakeCompiler.ts +++ b/Clava-JS/api/clava/cmake/compilers/GenericCMakeCompiler.ts @@ -1,4 +1,4 @@ -import CMakeCompiler from "./CMakeCompiler.js"; +import CMakeCompiler from "./CMakeCompiler.ts"; /** * Iterates over a list of values. diff --git a/Clava-JS/src-api/clava/code/DecomposeResult.ts b/Clava-JS/api/clava/code/DecomposeResult.ts similarity index 92% rename from Clava-JS/src-api/clava/code/DecomposeResult.ts rename to Clava-JS/api/clava/code/DecomposeResult.ts index 81648819a1..fa8edfe5e9 100644 --- a/Clava-JS/src-api/clava/code/DecomposeResult.ts +++ b/Clava-JS/api/clava/code/DecomposeResult.ts @@ -1,4 +1,4 @@ -import { Expression, Statement } from "../../Joinpoints.js"; +import { Expression, Statement } from "../../Joinpoints.ts"; export default class DecomposeResult { precedingStmts: Statement[]; diff --git a/Clava-JS/src-api/clava/code/DoToWhileStmt.ts b/Clava-JS/api/clava/code/DoToWhileStmt.ts similarity index 94% rename from Clava-JS/src-api/clava/code/DoToWhileStmt.ts rename to Clava-JS/api/clava/code/DoToWhileStmt.ts index 0c6d4b07db..0c97a1cfa1 100644 --- a/Clava-JS/src-api/clava/code/DoToWhileStmt.ts +++ b/Clava-JS/api/clava/code/DoToWhileStmt.ts @@ -1,5 +1,5 @@ -import { Joinpoint, Loop } from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +import { Joinpoint, Loop } from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; export default function DoToWhileStmt($doStmt: Loop, labelSuffix: number | string) { // do statements have an unconditional first iteration diff --git a/Clava-JS/src-api/clava/code/ForToWhileStmt.ts b/Clava-JS/api/clava/code/ForToWhileStmt.ts similarity index 95% rename from Clava-JS/src-api/clava/code/ForToWhileStmt.ts rename to Clava-JS/api/clava/code/ForToWhileStmt.ts index 50461555d1..4a9d4af209 100644 --- a/Clava-JS/src-api/clava/code/ForToWhileStmt.ts +++ b/Clava-JS/api/clava/code/ForToWhileStmt.ts @@ -1,5 +1,5 @@ -import { EmptyStmt, Joinpoint, Loop } from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +import { EmptyStmt, Joinpoint, Loop } from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; /** * Replaces for loop with an equivalent construct based on a while loop: diff --git a/Clava-JS/src-api/clava/code/GlobalVariable.ts b/Clava-JS/api/clava/code/GlobalVariable.ts similarity index 95% rename from Clava-JS/src-api/clava/code/GlobalVariable.ts rename to Clava-JS/api/clava/code/GlobalVariable.ts index ee251bc458..ef9c8718ed 100644 --- a/Clava-JS/src-api/clava/code/GlobalVariable.ts +++ b/Clava-JS/api/clava/code/GlobalVariable.ts @@ -1,5 +1,5 @@ -import { FileJp, Joinpoint, Type, Varref } from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +import { FileJp, Joinpoint, Type, Varref } from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; /** * Adds and manages global variables. diff --git a/Clava-JS/src-api/clava/code/Inliner.ts b/Clava-JS/api/clava/code/Inliner.ts similarity index 98% rename from Clava-JS/src-api/clava/code/Inliner.ts rename to Clava-JS/api/clava/code/Inliner.ts index 0ca32aa9d8..1bdeb8ac58 100644 --- a/Clava-JS/src-api/clava/code/Inliner.ts +++ b/Clava-JS/api/clava/code/Inliner.ts @@ -1,6 +1,6 @@ -import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js"; -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.ts"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { BinaryOp, Call, @@ -23,8 +23,8 @@ import { Vardecl, VariableArrayType, Varref, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; export interface InlinerOptions { prefix?: string; diff --git a/Clava-JS/src-api/clava/code/Outliner.ts b/Clava-JS/api/clava/code/Outliner.ts similarity index 96% rename from Clava-JS/src-api/clava/code/Outliner.ts rename to Clava-JS/api/clava/code/Outliner.ts index b999f497e0..26833ac281 100644 --- a/Clava-JS/src-api/clava/code/Outliner.ts +++ b/Clava-JS/api/clava/code/Outliner.ts @@ -1,5 +1,5 @@ -import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { AdjustedType, ArrayType, @@ -11,14 +11,15 @@ import { FileJp, FunctionJp, Joinpoint, + OpKind, Param, PointerType, ReturnStmt, Statement, Vardecl, Varref, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; export default class Outliner { private verbose: boolean = true; @@ -228,13 +229,13 @@ export default class Outliner { for (const ret of returnStmts) { const resVarParam = fun.params[fun.params.length - 2]; const derefResVarParam = ClavaJoinPoints.unaryOp( - "*", + OpKind.deref, resVarParam.varref() ); const retVal = ret.children[0]; retVal.detach(); const op1 = ClavaJoinPoints.binaryOp( - "=", + OpKind.eq, derefResVarParam, retVal as any, resVarParam.type @@ -243,10 +244,10 @@ export default class Outliner { const boolVarParam = fun.params[fun.params.length - 1]; const newVarref = ClavaJoinPoints.varRef(boolVarParam); - const derefBoolVarParam = ClavaJoinPoints.unaryOp("*", newVarref); + const derefBoolVarParam = ClavaJoinPoints.unaryOp(OpKind.deref, newVarref); const trueVal = ClavaJoinPoints.integerLiteral(1); const op2 = ClavaJoinPoints.binaryOp( - "=", + OpKind.eq, derefBoolVarParam, trueVal, boolVarParam.type @@ -256,8 +257,8 @@ export default class Outliner { fun.setType(ClavaJoinPoints.type("void")); // actions on the function call - const resVarAddr = ClavaJoinPoints.unaryOp("&", resVarRef); - const boolVarAddr = ClavaJoinPoints.unaryOp("&", boolVarRef); + const resVarAddr = ClavaJoinPoints.unaryOp(OpKind.addr_of, resVarRef); + const boolVarAddr = ClavaJoinPoints.unaryOp(OpKind.addr_of, boolVarRef); const allArgs = call.argList.concat([resVarAddr, boolVarAddr]); call = this.createCall(call, fun, allArgs); @@ -341,7 +342,7 @@ export default class Outliner { param.type instanceof PointerType && ref.type instanceof BuiltinType ) { - const addressOfScalar = ClavaJoinPoints.unaryOp("&", ref); + const addressOfScalar = ClavaJoinPoints.unaryOp(OpKind.addr_of, ref); args.push(addressOfScalar); } else { args.push(ref); @@ -409,7 +410,7 @@ export default class Outliner { varref.type instanceof BuiltinType ) { const newVarref = ClavaJoinPoints.varRef(param); - const op = ClavaJoinPoints.unaryOp("*", newVarref); + const op = ClavaJoinPoints.unaryOp(OpKind.deref, newVarref); varref.replaceWith(op); } } diff --git a/Clava-JS/src-api/clava/code/RemoveShadowing.ts b/Clava-JS/api/clava/code/RemoveShadowing.ts similarity index 90% rename from Clava-JS/src-api/clava/code/RemoveShadowing.ts rename to Clava-JS/api/clava/code/RemoveShadowing.ts index 205b984013..81fb4d6a6e 100644 --- a/Clava-JS/src-api/clava/code/RemoveShadowing.ts +++ b/Clava-JS/api/clava/code/RemoveShadowing.ts @@ -1,4 +1,4 @@ -import { FunctionJp, Vardecl } from "../../Joinpoints.js"; +import { FunctionJp, Vardecl } from "../../Joinpoints.ts"; export default function RemoveShadowing($function: FunctionJp): void { const usedNames = new Set(); diff --git a/Clava-JS/src-api/clava/code/SimplifyAssignment.ts b/Clava-JS/api/clava/code/SimplifyAssignment.ts similarity index 54% rename from Clava-JS/src-api/clava/code/SimplifyAssignment.ts rename to Clava-JS/api/clava/code/SimplifyAssignment.ts index 26338e9e27..7327677ea8 100644 --- a/Clava-JS/src-api/clava/code/SimplifyAssignment.ts +++ b/Clava-JS/api/clava/code/SimplifyAssignment.ts @@ -1,5 +1,5 @@ -import { BinaryOp, Expression } from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +import { BinaryOp, Expression, OpKind } from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; /** * Simplifies assignments of the type `a += b` into the equivalent expression `a = a + b` @@ -7,7 +7,7 @@ import ClavaJoinPoints from "../ClavaJoinPoints.js"; */ export default function SimplifyAssignment($complexAssignment: BinaryOp): void { // early return if current node is not suitable for this transform - if (!ops.has($complexAssignment.operator)) { + if (!ops.has($complexAssignment.kind)) { return; } @@ -15,7 +15,7 @@ export default function SimplifyAssignment($complexAssignment: BinaryOp): void { const $rValue = $complexAssignment.right; const $binaryOp = ClavaJoinPoints.binaryOp( - ops.get($complexAssignment.operator)!, + ops.get($complexAssignment.kind)!, $lValue.copy() as Expression, $rValue, $complexAssignment.type @@ -26,15 +26,15 @@ export default function SimplifyAssignment($complexAssignment: BinaryOp): void { /** * Non-assignment counterparts of complex assignment operators (lookup table) */ -const ops = new Map([ - ["*=", "*"], - ["/=", "/"], - ["%=", "%"], - ["+=", "+"], - ["-=", "-"], - ["<<=", "<<"], - [">>=", ">>"], - ["&=", "&"], - ["^=", "^"], - ["|=", "|"], +const ops = new Map([ + [OpKind.mul_assign, OpKind.mul], + [OpKind.div_assign, OpKind.div], + [OpKind.rem_assign, OpKind.rem], + [OpKind.add_assign, OpKind.add], + [OpKind.sub_assign, OpKind.sub], + [OpKind.shl_assign, OpKind.shl], + [OpKind.shr_assign, OpKind.shr], + [OpKind.and_assign, OpKind.and], + [OpKind.xor_assign, OpKind.xor], + [OpKind.or_assign, OpKind.or], ]); diff --git a/Clava-JS/src-api/clava/code/SimplifyTernaryOp.ts b/Clava-JS/api/clava/code/SimplifyTernaryOp.ts similarity index 96% rename from Clava-JS/src-api/clava/code/SimplifyTernaryOp.ts rename to Clava-JS/api/clava/code/SimplifyTernaryOp.ts index 8ba7813fdb..abbd538042 100644 --- a/Clava-JS/src-api/clava/code/SimplifyTernaryOp.ts +++ b/Clava-JS/api/clava/code/SimplifyTernaryOp.ts @@ -1,5 +1,5 @@ -import { BinaryOp, ExprStmt, TernaryOp } from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +import { BinaryOp, ExprStmt, TernaryOp } from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; /** * Simplifies a statement like: diff --git a/Clava-JS/src-api/clava/code/StatementDecomposer.ts b/Clava-JS/api/clava/code/StatementDecomposer.ts similarity index 95% rename from Clava-JS/src-api/clava/code/StatementDecomposer.ts rename to Clava-JS/api/clava/code/StatementDecomposer.ts index ffba11fbb7..675125d501 100644 --- a/Clava-JS/src-api/clava/code/StatementDecomposer.ts +++ b/Clava-JS/api/clava/code/StatementDecomposer.ts @@ -1,4 +1,4 @@ -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; import { BinaryOp, Call, @@ -11,15 +11,16 @@ import { Joinpoint, LabelStmt, MemberCall, + OpKind, ReturnStmt, Scope, Statement, TernaryOp, UnaryOp, Vardecl, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import DecomposeResult from "./DecomposeResult.js"; +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import DecomposeResult from "./DecomposeResult.ts"; /** * Decomposes complex statements into several simpler ones. @@ -332,10 +333,10 @@ export default class StatementDecomposer { const rightResult = this.decomposeExpr($assign.right); const $newAssign = - $assign.operator === "=" + $assign.kind === OpKind.assign ? ClavaJoinPoints.assign($assign.left, rightResult.$resultExpr) : ClavaJoinPoints.compoundAssign( - $assign.operator, + $assign.kind, $assign.left, rightResult.$resultExpr ); @@ -407,23 +408,23 @@ export default class StatementDecomposer { // only decompose increment / decrement operations, separating the change // from the result of the change if ( - kind !== "post_dec" && - kind !== "post_inc" && - kind !== "pre_dec" && - kind !== "pre_inc" + kind !== OpKind.post_dec && + kind !== OpKind.post_inc && + kind !== OpKind.pre_dec && + kind !== OpKind.pre_inc ) { return new DecomposeResult([], $unaryOp, []); } switch (kind) { - case "post_dec": - case "post_inc": { + case OpKind.post_dec: + case OpKind.post_inc: { const $innerExpr = $unaryOp.operand.copy() as Expression; const succeedingStmts = [ClavaJoinPoints.exprStmt($unaryOp)]; return new DecomposeResult([], $innerExpr, succeedingStmts); } - case "pre_dec": - case "pre_inc": { + case OpKind.pre_dec: + case OpKind.pre_inc: { const $innerExpr = $unaryOp.operand.copy() as Expression; const precedingStmts = [ClavaJoinPoints.exprStmt($unaryOp)]; return new DecomposeResult(precedingStmts, $innerExpr, []); diff --git a/Clava-JS/src-api/clava/gprofer/Gprofer.ts b/Clava-JS/api/clava/gprofer/Gprofer.ts similarity index 93% rename from Clava-JS/src-api/clava/gprofer/Gprofer.ts rename to Clava-JS/api/clava/gprofer/Gprofer.ts index 8b12018270..35c9988490 100644 --- a/Clava-JS/src-api/clava/gprofer/Gprofer.ts +++ b/Clava-JS/api/clava/gprofer/Gprofer.ts @@ -1,13 +1,13 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import Strings from "@specs-feup/lara/api/lara/Strings.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import Strings from "@specs-feup/lara/api/lara/Strings.ts"; import JavaTypes, { - JavaClasses, -} from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { FileJp, FunctionJp } from "../../Joinpoints.js"; -import Clava from "../Clava.js"; -import CMaker from "../cmake/CMaker.js"; -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; + type JavaClasses, +} from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { FileJp, FunctionJp } from "../../Joinpoints.ts"; +import Clava from "../Clava.ts"; +import CMaker from "../cmake/CMaker.ts"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; function GproferGetCxxFunction(signature: string) { return Query.search(FunctionJp, { diff --git a/Clava-JS/src-api/clava/graphs/ControlFlowGraph.ts b/Clava-JS/api/clava/graphs/ControlFlowGraph.ts similarity index 93% rename from Clava-JS/src-api/clava/graphs/ControlFlowGraph.ts rename to Clava-JS/api/clava/graphs/ControlFlowGraph.ts index dbc93107a7..335742a988 100644 --- a/Clava-JS/src-api/clava/graphs/ControlFlowGraph.ts +++ b/Clava-JS/api/clava/graphs/ControlFlowGraph.ts @@ -1,7 +1,7 @@ -import Graph from "@specs-feup/lara/api/lara/graphs/Graph.js"; +import Graph from "@specs-feup/lara/api/lara/graphs/Graph.ts"; import cytoscape from "cytoscape"; -import { Statement } from "../../Joinpoints.js"; -import CfgBuilder from "./cfg/CfgBuilder.js"; +import { Statement } from "../../Joinpoints.ts"; +import CfgBuilder from "./cfg/CfgBuilder.ts"; export default class ControlFlowGraph extends Graph { /** diff --git a/Clava-JS/src-api/clava/graphs/StaticCallGraph.ts b/Clava-JS/api/clava/graphs/StaticCallGraph.ts similarity index 87% rename from Clava-JS/src-api/clava/graphs/StaticCallGraph.ts rename to Clava-JS/api/clava/graphs/StaticCallGraph.ts index b28f2edea2..7155ef0868 100644 --- a/Clava-JS/src-api/clava/graphs/StaticCallGraph.ts +++ b/Clava-JS/api/clava/graphs/StaticCallGraph.ts @@ -1,10 +1,10 @@ -import DotFormatter from "@specs-feup/lara/api/lara/graphs/DotFormatter.js"; -import Graph from "@specs-feup/lara/api/lara/graphs/Graph.js"; -import Graphs from "@specs-feup/lara/api/lara/graphs/Graphs.js"; +import DotFormatter from "@specs-feup/lara/api/lara/graphs/DotFormatter.ts"; +import Graph from "@specs-feup/lara/api/lara/graphs/Graph.ts"; +import Graphs from "@specs-feup/lara/api/lara/graphs/Graphs.ts"; import cytoscape from "cytoscape"; -import { FunctionJp, Joinpoint } from "../../Joinpoints.js"; -import ScgNodeData from "./scg/ScgNodeData.js"; -import StaticCallGraphBuilder from "./scg/StaticCallGraphBuilder.js"; +import { FunctionJp, Joinpoint } from "../../Joinpoints.ts"; +import ScgNodeData from "./scg/ScgNodeData.ts"; +import StaticCallGraphBuilder from "./scg/StaticCallGraphBuilder.ts"; export default class StaticCallGraph extends Graph { private static dotFormatterInstance: DotFormatter | undefined = undefined; diff --git a/Clava-JS/src-api/clava/graphs/cfg/CfgBuilder.ts b/Clava-JS/api/clava/graphs/cfg/CfgBuilder.ts similarity index 95% rename from Clava-JS/src-api/clava/graphs/cfg/CfgBuilder.ts rename to Clava-JS/api/clava/graphs/cfg/CfgBuilder.ts index e2a4e46d99..0b279d7724 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/CfgBuilder.ts +++ b/Clava-JS/api/clava/graphs/cfg/CfgBuilder.ts @@ -1,7 +1,7 @@ -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import Graphs from "@specs-feup/lara/api/lara/graphs/Graphs.js"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import Graphs from "@specs-feup/lara/api/lara/graphs/Graphs.ts"; import cytoscape from "cytoscape"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { Break, Continue, @@ -9,28 +9,29 @@ import { LabelDecl, LabelStmt, Loop, + LoopKind, Scope, Statement, Switch, -} from "../../../Joinpoints.js"; -import ClavaJoinPoints from "../../ClavaJoinPoints.js"; -import CfgEdge from "./CfgEdge.js"; -import CfgEdgeType from "./CfgEdgeType.js"; -import CfgNodeData from "./CfgNodeData.js"; -import CfgNodeType from "./CfgNodeType.js"; -import CfgUtils from "./CfgUtils.js"; -import NextCfgNode from "./NextCfgNode.js"; -import CaseData from "./nodedata/CaseData.js"; -import DataFactory from "./nodedata/DataFactory.js"; -import HeaderData from "./nodedata/HeaderData.js"; -import IfData from "./nodedata/IfData.js"; -import InstListNodeData from "./nodedata/InstListNodeData.js"; -import LoopData from "./nodedata/LoopData.js"; -import ScopeNodeData from "./nodedata/ScopeNodeData.js"; -import SwitchData from "./nodedata/SwitchData.js"; -import GotoData from "./nodedata/GotoData.js"; -import LabelData from "./nodedata/LabelData.js"; -import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js"; +} from "../../../Joinpoints.ts"; +import ClavaJoinPoints from "../../ClavaJoinPoints.ts"; +import CfgEdge from "./CfgEdge.ts"; +import CfgEdgeType from "./CfgEdgeType.ts"; +import CfgNodeData from "./CfgNodeData.ts"; +import CfgNodeType from "./CfgNodeType.ts"; +import CfgUtils from "./CfgUtils.ts"; +import NextCfgNode from "./NextCfgNode.ts"; +import CaseData from "./nodedata/CaseData.ts"; +import DataFactory from "./nodedata/DataFactory.ts"; +import HeaderData from "./nodedata/HeaderData.ts"; +import IfData from "./nodedata/IfData.ts"; +import InstListNodeData from "./nodedata/InstListNodeData.ts"; +import LoopData from "./nodedata/LoopData.ts"; +import ScopeNodeData from "./nodedata/ScopeNodeData.ts"; +import SwitchData from "./nodedata/SwitchData.ts"; +import GotoData from "./nodedata/GotoData.ts"; +import LabelData from "./nodedata/LabelData.ts"; +import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.ts"; export default class CfgBuilder { /** @@ -335,13 +336,13 @@ export default class CfgBuilder { let afterStmt = undefined; switch ($loop.kind) { - case "for": + case LoopKind.for: afterStmt = $loop.init; break; - case "while": + case LoopKind.while: afterStmt = $loop.cond; break; - case "dowhile": + case LoopKind.dowhile: afterStmt = $loop.body; break; default: @@ -420,7 +421,7 @@ export default class CfgBuilder { throw new Error("Loop is undefined"); } - const $afterStmt = $loop.kind === "for" ? $loop.step : $loop.cond; + const $afterStmt = $loop.kind === LoopKind.for ? $loop.step : $loop.cond; const afterNode = this.nodes.get($afterStmt.astId) ?? this.endNode; this.addEdge(node, afterNode, CfgEdgeType.UNCONDITIONAL); @@ -526,7 +527,7 @@ export default class CfgBuilder { throw new Error("$loop is not an instance of Loop"); } - if ($loop.kind !== "for") { + if ($loop.kind !== LoopKind.for) { throw new Error("Not implemented for loops of kind " + $loop.kind); } @@ -563,7 +564,7 @@ export default class CfgBuilder { throw new Error("$loop is not an instance of Loop"); } - if ($loop.kind !== "for") { + if ($loop.kind !== LoopKind.for) { throw new Error("Not implemented for loops of kind " + $loop.kind); } diff --git a/Clava-JS/src-api/clava/graphs/cfg/CfgEdge.ts b/Clava-JS/api/clava/graphs/cfg/CfgEdge.ts similarity index 94% rename from Clava-JS/src-api/clava/graphs/cfg/CfgEdge.ts rename to Clava-JS/api/clava/graphs/cfg/CfgEdge.ts index ec0c591218..543a869cb6 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/CfgEdge.ts +++ b/Clava-JS/api/clava/graphs/cfg/CfgEdge.ts @@ -1,5 +1,5 @@ -import EdgeData from "@specs-feup/lara/api/lara/graphs/EdgeData.js"; -import CfgEdgeType from "./CfgEdgeType.js"; +import EdgeData from "@specs-feup/lara/api/lara/graphs/EdgeData.ts"; +import CfgEdgeType from "./CfgEdgeType.ts"; /** * An edge of the CFG diff --git a/Clava-JS/src-api/clava/graphs/cfg/CfgEdgeType.ts b/Clava-JS/api/clava/graphs/cfg/CfgEdgeType.ts similarity index 100% rename from Clava-JS/src-api/clava/graphs/cfg/CfgEdgeType.ts rename to Clava-JS/api/clava/graphs/cfg/CfgEdgeType.ts diff --git a/Clava-JS/src-api/clava/graphs/cfg/CfgNodeData.ts b/Clava-JS/api/clava/graphs/cfg/CfgNodeData.ts similarity index 95% rename from Clava-JS/src-api/clava/graphs/cfg/CfgNodeData.ts rename to Clava-JS/api/clava/graphs/cfg/CfgNodeData.ts index c35eb7903d..628453511a 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/CfgNodeData.ts +++ b/Clava-JS/api/clava/graphs/cfg/CfgNodeData.ts @@ -1,6 +1,6 @@ -import NodeData from "@specs-feup/lara/api/lara/graphs/NodeData.js"; -import { Statement } from "../../../Joinpoints.js"; -import CfgNodeType from "./CfgNodeType.js"; +import NodeData from "@specs-feup/lara/api/lara/graphs/NodeData.ts"; +import { Statement } from "../../../Joinpoints.ts"; +import CfgNodeType from "./CfgNodeType.ts"; /** * The data of a CFG node. diff --git a/Clava-JS/src-api/clava/graphs/cfg/CfgNodeType.ts b/Clava-JS/api/clava/graphs/cfg/CfgNodeType.ts similarity index 100% rename from Clava-JS/src-api/clava/graphs/cfg/CfgNodeType.ts rename to Clava-JS/api/clava/graphs/cfg/CfgNodeType.ts diff --git a/Clava-JS/src-api/clava/graphs/cfg/CfgUtils.ts b/Clava-JS/api/clava/graphs/cfg/CfgUtils.ts similarity index 96% rename from Clava-JS/src-api/clava/graphs/cfg/CfgUtils.ts rename to Clava-JS/api/clava/graphs/cfg/CfgUtils.ts index 02507f6bec..b1e268aab9 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/CfgUtils.ts +++ b/Clava-JS/api/clava/graphs/cfg/CfgUtils.ts @@ -11,10 +11,10 @@ import { Scope, Statement, Switch, -} from "../../../Joinpoints.js"; -import CfgEdge from "./CfgEdge.js"; -import CfgEdgeType from "./CfgEdgeType.js"; -import CfgNodeType from "./CfgNodeType.js"; +} from "../../../Joinpoints.ts"; +import CfgEdge from "./CfgEdge.ts"; +import CfgEdgeType from "./CfgEdgeType.ts"; +import CfgNodeType from "./CfgNodeType.ts"; export default class CfgUtils { /** diff --git a/Clava-JS/src-api/clava/graphs/cfg/NextCfgNode.ts b/Clava-JS/api/clava/graphs/cfg/NextCfgNode.ts similarity index 97% rename from Clava-JS/src-api/clava/graphs/cfg/NextCfgNode.ts rename to Clava-JS/api/clava/graphs/cfg/NextCfgNode.ts index 02493c0aa7..c1981e3957 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/NextCfgNode.ts +++ b/Clava-JS/api/clava/graphs/cfg/NextCfgNode.ts @@ -4,9 +4,10 @@ import { FunctionJp, If, Loop, + LoopKind, Scope, Statement, -} from "../../../Joinpoints.js"; +} from "../../../Joinpoints.ts"; export default class NextCfgNode { /** @@ -117,15 +118,15 @@ export default class NextCfgNode { // Next stmt is what comes next of if switch ($scopeParent.kind) { - case "while": - case "dowhile": + case LoopKind.while: + case LoopKind.dowhile: if ($scopeParent.cond === undefined) { throw new Error( "Not implemented when for loops do not have a condition statement" ); } return $scopeParent.cond; - case "for": + case LoopKind.for: if ($scopeParent.step === undefined) { throw new Error( "Not implemented when for loops do not have a step statement" diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/CaseData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/CaseData.ts similarity index 77% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/CaseData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/CaseData.ts index a7946bb6fc..0402b0bc69 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/CaseData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/CaseData.ts @@ -1,6 +1,6 @@ -import { Case } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { Case } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class CaseData extends CfgNodeData { constructor($stmt?: Case, id?: string) { diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/DataFactory.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/DataFactory.ts similarity index 81% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/DataFactory.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/DataFactory.ts index 3b274059fd..70e59a2fd0 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/DataFactory.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/DataFactory.ts @@ -8,19 +8,19 @@ import { Scope, Statement, Switch, -} from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; -import CaseData from "./CaseData.js"; -import GotoData from "./GotoData.js"; -import HeaderData from "./HeaderData.js"; -import IfData from "./IfData.js"; -import InstListNodeData from "./InstListNodeData.js"; -import LabelData from "./LabelData.js"; -import LoopData from "./LoopData.js"; -import ReturnData from "./ReturnData.js"; -import ScopeNodeData from "./ScopeNodeData.js"; -import SwitchData from "./SwitchData.js"; +} from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; +import CaseData from "./CaseData.ts"; +import GotoData from "./GotoData.ts"; +import HeaderData from "./HeaderData.ts"; +import IfData from "./IfData.ts"; +import InstListNodeData from "./InstListNodeData.ts"; +import LabelData from "./LabelData.ts"; +import LoopData from "./LoopData.ts"; +import ReturnData from "./ReturnData.ts"; +import ScopeNodeData from "./ScopeNodeData.ts"; +import SwitchData from "./SwitchData.ts"; export default class DataFactory { private entryPoint: Statement; diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/GotoData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/GotoData.ts similarity index 69% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/GotoData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/GotoData.ts index 82f9ed8b04..a331483cf3 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/GotoData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/GotoData.ts @@ -1,6 +1,6 @@ -import { GotoStmt } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { GotoStmt } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class GotoData extends CfgNodeData { constructor($stmt?: GotoStmt, id?: string) { diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/HeaderData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/HeaderData.ts similarity index 76% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/HeaderData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/HeaderData.ts index 909cd0821d..7c35ed28d5 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/HeaderData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/HeaderData.ts @@ -1,6 +1,6 @@ -import { Statement } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { Statement } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class HeaderData extends CfgNodeData { constructor($stmt: Statement | undefined, nodeType: CfgNodeType, id: string | undefined) { diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/IfData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/IfData.ts similarity index 72% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/IfData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/IfData.ts index 657dacd09b..492c44980b 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/IfData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/IfData.ts @@ -1,6 +1,6 @@ -import { If } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { If } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class IfData extends CfgNodeData { constructor($stmt?: If, id?: string) { diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/InstListNodeData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/InstListNodeData.ts similarity index 89% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/InstListNodeData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/InstListNodeData.ts index 8640504648..f262629f98 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/InstListNodeData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/InstListNodeData.ts @@ -1,7 +1,7 @@ -import { Statement } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; -import CfgUtils from "../CfgUtils.js"; +import { Statement } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; +import CfgUtils from "../CfgUtils.ts"; type T = Statement; diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/LabelData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/LabelData.ts similarity index 69% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/LabelData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/LabelData.ts index 86a6d06853..a9d7d1287b 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/LabelData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/LabelData.ts @@ -1,6 +1,6 @@ -import { LabelStmt } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { LabelStmt } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class LabelData extends CfgNodeData { constructor($stmt?: LabelStmt, id?: string) { diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/LoopData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/LoopData.ts similarity index 70% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/LoopData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/LoopData.ts index 876262fe56..26cce07896 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/LoopData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/LoopData.ts @@ -1,6 +1,6 @@ -import { Loop } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { Loop } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class LoopData extends CfgNodeData { constructor($stmt?: Loop, id?: string) { diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/ReturnData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/ReturnData.ts similarity index 72% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/ReturnData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/ReturnData.ts index 775b9ef6c7..e57060a73d 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/ReturnData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/ReturnData.ts @@ -1,6 +1,6 @@ -import { ReturnStmt } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { ReturnStmt } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class ReturnData extends CfgNodeData { constructor($stmt?: ReturnStmt, id?: string) { diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/ScopeNodeData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/ScopeNodeData.ts similarity index 66% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/ScopeNodeData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/ScopeNodeData.ts index c91d53c4e5..55334b4dba 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/ScopeNodeData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/ScopeNodeData.ts @@ -1,6 +1,6 @@ -import { Scope } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { Scope } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class ScopeNodeData extends CfgNodeData { private scopeStmt; diff --git a/Clava-JS/src-api/clava/graphs/cfg/nodedata/SwitchData.ts b/Clava-JS/api/clava/graphs/cfg/nodedata/SwitchData.ts similarity index 73% rename from Clava-JS/src-api/clava/graphs/cfg/nodedata/SwitchData.ts rename to Clava-JS/api/clava/graphs/cfg/nodedata/SwitchData.ts index 18c71188b2..7b28154c57 100644 --- a/Clava-JS/src-api/clava/graphs/cfg/nodedata/SwitchData.ts +++ b/Clava-JS/api/clava/graphs/cfg/nodedata/SwitchData.ts @@ -1,6 +1,6 @@ -import { Switch } from "../../../../Joinpoints.js"; -import CfgNodeData from "../CfgNodeData.js"; -import CfgNodeType from "../CfgNodeType.js"; +import { Switch } from "../../../../Joinpoints.ts"; +import CfgNodeData from "../CfgNodeData.ts"; +import CfgNodeType from "../CfgNodeType.ts"; export default class SwitchData extends CfgNodeData { constructor($stmt?: Switch, id?: string) { diff --git a/Clava-JS/src-api/clava/graphs/scg/ScgEdgeData.ts b/Clava-JS/api/clava/graphs/scg/ScgEdgeData.ts similarity index 88% rename from Clava-JS/src-api/clava/graphs/scg/ScgEdgeData.ts rename to Clava-JS/api/clava/graphs/scg/ScgEdgeData.ts index 1541821c64..fe08502a18 100644 --- a/Clava-JS/src-api/clava/graphs/scg/ScgEdgeData.ts +++ b/Clava-JS/api/clava/graphs/scg/ScgEdgeData.ts @@ -1,5 +1,5 @@ -import EdgeData from "@specs-feup/lara/api/lara/graphs/EdgeData.js"; -import { Call } from "../../../Joinpoints.js"; +import EdgeData from "@specs-feup/lara/api/lara/graphs/EdgeData.ts"; +import { Call } from "../../../Joinpoints.ts"; export default class ScgEdgeData extends EdgeData { /** diff --git a/Clava-JS/src-api/clava/graphs/scg/ScgNodeData.ts b/Clava-JS/api/clava/graphs/scg/ScgNodeData.ts similarity index 86% rename from Clava-JS/src-api/clava/graphs/scg/ScgNodeData.ts rename to Clava-JS/api/clava/graphs/scg/ScgNodeData.ts index 147227ec2a..042f2d086a 100644 --- a/Clava-JS/src-api/clava/graphs/scg/ScgNodeData.ts +++ b/Clava-JS/api/clava/graphs/scg/ScgNodeData.ts @@ -1,6 +1,6 @@ -import NodeData from "@specs-feup/lara/api/lara/graphs/NodeData.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { Call, FunctionJp } from "../../../Joinpoints.js"; +import NodeData from "@specs-feup/lara/api/lara/graphs/NodeData.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { Call, FunctionJp } from "../../../Joinpoints.ts"; export default class ScgNodeData extends NodeData { /** diff --git a/Clava-JS/src-api/clava/graphs/scg/StaticCallGraphBuilder.ts b/Clava-JS/api/clava/graphs/scg/StaticCallGraphBuilder.ts similarity index 95% rename from Clava-JS/src-api/clava/graphs/scg/StaticCallGraphBuilder.ts rename to Clava-JS/api/clava/graphs/scg/StaticCallGraphBuilder.ts index 8a00b55d35..f22959cbd7 100644 --- a/Clava-JS/src-api/clava/graphs/scg/StaticCallGraphBuilder.ts +++ b/Clava-JS/api/clava/graphs/scg/StaticCallGraphBuilder.ts @@ -1,10 +1,10 @@ -import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js"; -import Graphs from "@specs-feup/lara/api/lara/graphs/Graphs.js"; +import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.ts"; +import Graphs from "@specs-feup/lara/api/lara/graphs/Graphs.ts"; import cytoscape from "cytoscape"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { Call, FunctionJp, Joinpoint, Program } from "../../../Joinpoints.js"; -import ScgEdgeData from "./ScgEdgeData.js"; -import ScgNodeData from "./ScgNodeData.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { Call, FunctionJp, Joinpoint, Program } from "../../../Joinpoints.ts"; +import ScgEdgeData from "./ScgEdgeData.ts"; +import ScgNodeData from "./ScgNodeData.ts"; export default class StaticCallGraphBuilder { /** diff --git a/Clava-JS/src-api/clava/hdf5/Hdf5.ts b/Clava-JS/api/clava/hdf5/Hdf5.ts similarity index 82% rename from Clava-JS/src-api/clava/hdf5/Hdf5.ts rename to Clava-JS/api/clava/hdf5/Hdf5.ts index c626aca7c3..1a0905f0cb 100644 --- a/Clava-JS/src-api/clava/hdf5/Hdf5.ts +++ b/Clava-JS/api/clava/hdf5/Hdf5.ts @@ -5,35 +5,41 @@ import { RecordJp, TemplateSpecializationType, Type, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import Format from "../Format.js"; - -enum HDF5Types { - "char" = "C_S1", - "signed char" = "NATIVE_SCHAR", - "unsigned char" = "NATIVE_UCHAR", - "short" = "NATIVE_SHORT", - "unsigned short" = "NATIVE_USHORT", - "int" = "NATIVE_INT", - "unsigned int" = "NATIVE_UINT", - "long" = "NATIVE_LONG", - "unsigned long" = "NATIVE_ULONG", - "long long" = "NATIVE_LLONG", - "unsigned long long" = "NATIVE_ULLONG", - "float" = "NATIVE_FLOAT", - "double" = "NATIVE_DOUBLE", - "long double" = "NATIVE_LDOUBLE", - - "int8_t" = "NATIVE_INT8", - "uint8_t" = "NATIVE_UINT8", - "int16_t" = "NATIVE_INT16", - "uint16_t" = "NATIVE_UINT16", - "int32_t" = "NATIVE_INT32", - "uin32_t" = "NATIVE_UINT32", - "int64_t" = "NATIVE_INT64", - "uint64_t" = "NATIVE_UINT64", -} +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import Format from "../Format.ts"; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +const HDF5Types = { + "char": "C_S1", + "signed char": "NATIVE_SCHAR", + "unsigned char": "NATIVE_UCHAR", + "short": "NATIVE_SHORT", + "unsigned short": "NATIVE_USHORT", + "int": "NATIVE_INT", + "unsigned int": "NATIVE_UINT", + "long": "NATIVE_LONG", + "unsigned long": "NATIVE_ULONG", + "long long": "NATIVE_LLONG", + "unsigned long long": "NATIVE_ULLONG", + "float": "NATIVE_FLOAT", + "double": "NATIVE_DOUBLE", + "long double": "NATIVE_LDOUBLE", + + "int8_t": "NATIVE_INT8", + "uint8_t": "NATIVE_UINT8", + "int16_t": "NATIVE_INT16", + "uint16_t": "NATIVE_UINT16", + "int32_t": "NATIVE_INT32", + "uint32_t": "NATIVE_UINT32", + "int64_t": "NATIVE_INT64", + "uint64_t": "NATIVE_UINT64", +} as const; +type HDF5Types = typeof HDF5Types[keyof typeof HDF5Types]; /** * Utility methods related to the HDF5 library. diff --git a/Clava-JS/src-api/clava/liveness/LivenessAnalyser.ts b/Clava-JS/api/clava/liveness/LivenessAnalyser.ts similarity index 96% rename from Clava-JS/src-api/clava/liveness/LivenessAnalyser.ts rename to Clava-JS/api/clava/liveness/LivenessAnalyser.ts index 1267b9aa7d..8ca5928b69 100644 --- a/Clava-JS/src-api/clava/liveness/LivenessAnalyser.ts +++ b/Clava-JS/api/clava/liveness/LivenessAnalyser.ts @@ -1,9 +1,9 @@ import cytoscape from "cytoscape"; -import { Case, Expression, If, Statement, Switch } from "../../Joinpoints.js"; -import ControlFlowGraph from "../graphs/ControlFlowGraph.js"; -import CfgNodeData from "../graphs/cfg/CfgNodeData.js"; -import CfgNodeType from "../graphs/cfg/CfgNodeType.js"; -import LivenessUtils from "./LivenessUtils.js"; +import { Case, Expression, If, Statement, Switch } from "../../Joinpoints.ts"; +import ControlFlowGraph from "../graphs/ControlFlowGraph.ts"; +import CfgNodeData from "../graphs/cfg/CfgNodeData.ts"; +import CfgNodeType from "../graphs/cfg/CfgNodeType.ts"; +import LivenessUtils from "./LivenessUtils.ts"; export default class LivenessAnalyser { /** diff --git a/Clava-JS/src-api/clava/liveness/LivenessAnalysis.ts b/Clava-JS/api/clava/liveness/LivenessAnalysis.ts similarity index 95% rename from Clava-JS/src-api/clava/liveness/LivenessAnalysis.ts rename to Clava-JS/api/clava/liveness/LivenessAnalysis.ts index e2c9ab7263..808cfcb807 100644 --- a/Clava-JS/src-api/clava/liveness/LivenessAnalysis.ts +++ b/Clava-JS/api/clava/liveness/LivenessAnalysis.ts @@ -1,6 +1,6 @@ import cytoscape from "cytoscape"; -import ControlFlowGraph from "../graphs/ControlFlowGraph.js"; -import LivenessAnalyser from "./LivenessAnalyser.js"; +import ControlFlowGraph from "../graphs/ControlFlowGraph.ts"; +import LivenessAnalyser from "./LivenessAnalyser.ts"; export default class LivenessAnalysis { /** diff --git a/Clava-JS/src-api/clava/liveness/LivenessUtils.ts b/Clava-JS/api/clava/liveness/LivenessUtils.ts similarity index 98% rename from Clava-JS/src-api/clava/liveness/LivenessUtils.ts rename to Clava-JS/api/clava/liveness/LivenessUtils.ts index ed65bcb7c0..d2601f36b5 100644 --- a/Clava-JS/src-api/clava/liveness/LivenessUtils.ts +++ b/Clava-JS/api/clava/liveness/LivenessUtils.ts @@ -1,13 +1,13 @@ -import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js"; +import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.ts"; import cytoscape from "cytoscape"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { BinaryOp, Expression, Statement, Vardecl, Varref, -} from "../../Joinpoints.js"; +} from "../../Joinpoints.ts"; export default class LivenessUtils { /** diff --git a/Clava-JS/src-api/clava/mpi/MpiAccessPattern.ts b/Clava-JS/api/clava/mpi/MpiAccessPattern.ts similarity index 91% rename from Clava-JS/src-api/clava/mpi/MpiAccessPattern.ts rename to Clava-JS/api/clava/mpi/MpiAccessPattern.ts index 652d7ec288..5573aa6cdb 100644 --- a/Clava-JS/src-api/clava/mpi/MpiAccessPattern.ts +++ b/Clava-JS/api/clava/mpi/MpiAccessPattern.ts @@ -1,4 +1,4 @@ -import { Varref } from "../../Joinpoints.js"; +import { Varref } from "../../Joinpoints.ts"; /** * Represents an MPI access pattern. diff --git a/Clava-JS/src-api/clava/mpi/MpiScatterGatherLoop.ts b/Clava-JS/api/clava/mpi/MpiScatterGatherLoop.ts similarity index 97% rename from Clava-JS/src-api/clava/mpi/MpiScatterGatherLoop.ts rename to Clava-JS/api/clava/mpi/MpiScatterGatherLoop.ts index c92d3e664a..063cfec669 100644 --- a/Clava-JS/src-api/clava/mpi/MpiScatterGatherLoop.ts +++ b/Clava-JS/api/clava/mpi/MpiScatterGatherLoop.ts @@ -1,9 +1,9 @@ -import { FileJp, FunctionJp, Loop, Varref } from "../../Joinpoints.js"; -import ClavaCode from "../ClavaCode.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import MpiAccessPattern from "./MpiAccessPattern.js"; -import MpiUtils from "./MpiUtils.js"; -import MpiAccessPatterns from "./patterns/MpiAccessPatterns.js"; +import { FileJp, FunctionJp, Loop, Varref } from "../../Joinpoints.ts"; +import ClavaCode from "../ClavaCode.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import MpiAccessPattern from "./MpiAccessPattern.ts"; +import MpiUtils from "./MpiUtils.ts"; +import MpiAccessPatterns from "./patterns/MpiAccessPatterns.ts"; /** * Applies an MPI scatter-gather strategy to loops. diff --git a/Clava-JS/src-api/clava/mpi/MpiUtils.ts b/Clava-JS/api/clava/mpi/MpiUtils.ts similarity index 90% rename from Clava-JS/src-api/clava/mpi/MpiUtils.ts rename to Clava-JS/api/clava/mpi/MpiUtils.ts index d57f4600f8..43c1950e77 100644 --- a/Clava-JS/src-api/clava/mpi/MpiUtils.ts +++ b/Clava-JS/api/clava/mpi/MpiUtils.ts @@ -1,4 +1,4 @@ -import { BuiltinType, Type } from "../../Joinpoints.js"; +import { BuiltinType, Type } from "../../Joinpoints.ts"; /** * Utility methods related to MPI. diff --git a/Clava-JS/src-api/clava/mpi/patterns/IterationVariablePattern.ts b/Clava-JS/api/clava/mpi/patterns/IterationVariablePattern.ts similarity index 97% rename from Clava-JS/src-api/clava/mpi/patterns/IterationVariablePattern.ts rename to Clava-JS/api/clava/mpi/patterns/IterationVariablePattern.ts index 49fb0b3683..2c49e27ba6 100644 --- a/Clava-JS/src-api/clava/mpi/patterns/IterationVariablePattern.ts +++ b/Clava-JS/api/clava/mpi/patterns/IterationVariablePattern.ts @@ -1,7 +1,7 @@ -import MpiAccessPattern from "../MpiAccessPattern.js"; -import MpiUtils from "../MpiUtils.js"; -import ClavaJoinPoints from "../../ClavaJoinPoints.js"; -import { ArrayType, PointerType, Type, Varref } from "../../../Joinpoints.js"; +import MpiAccessPattern from "../MpiAccessPattern.ts"; +import MpiUtils from "../MpiUtils.ts"; +import ClavaJoinPoints from "../../ClavaJoinPoints.ts"; +import { ArrayType, PointerType, Type, Varref } from "../../../Joinpoints.ts"; /** * Array that is accessed using only the iteration variable directly, without modifications. diff --git a/Clava-JS/src-api/clava/mpi/patterns/MpiAccessPatterns.ts b/Clava-JS/api/clava/mpi/patterns/MpiAccessPatterns.ts similarity index 88% rename from Clava-JS/src-api/clava/mpi/patterns/MpiAccessPatterns.ts rename to Clava-JS/api/clava/mpi/patterns/MpiAccessPatterns.ts index b7197d827b..ef50b8e1d6 100644 --- a/Clava-JS/src-api/clava/mpi/patterns/MpiAccessPatterns.ts +++ b/Clava-JS/api/clava/mpi/patterns/MpiAccessPatterns.ts @@ -1,5 +1,5 @@ -import ScalarPattern from "./ScalarPattern.js"; -import IterationVariablePattern from "./IterationVariablePattern.js"; +import ScalarPattern from "./ScalarPattern.ts"; +import IterationVariablePattern from "./IterationVariablePattern.ts"; /** diff --git a/Clava-JS/src-api/clava/mpi/patterns/ScalarPattern.ts b/Clava-JS/api/clava/mpi/patterns/ScalarPattern.ts similarity index 85% rename from Clava-JS/src-api/clava/mpi/patterns/ScalarPattern.ts rename to Clava-JS/api/clava/mpi/patterns/ScalarPattern.ts index ad0216d2d7..b6d4aa0622 100644 --- a/Clava-JS/src-api/clava/mpi/patterns/ScalarPattern.ts +++ b/Clava-JS/api/clava/mpi/patterns/ScalarPattern.ts @@ -1,5 +1,5 @@ -import { Varref } from '../../../Joinpoints.js'; -import MpiAccessPattern from '../MpiAccessPattern.js'; +import { Varref } from '../../../Joinpoints.ts'; +import MpiAccessPattern from '../MpiAccessPattern.ts'; /** * Access to a scalar variable. diff --git a/Clava-JS/src-api/clava/opencl/KernelReplacer.ts b/Clava-JS/api/clava/opencl/KernelReplacer.ts similarity index 88% rename from Clava-JS/src-api/clava/opencl/KernelReplacer.ts rename to Clava-JS/api/clava/opencl/KernelReplacer.ts index 3f85c2babd..1197165aba 100644 --- a/Clava-JS/src-api/clava/opencl/KernelReplacer.ts +++ b/Clava-JS/api/clava/opencl/KernelReplacer.ts @@ -1,5 +1,5 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import Strings from "@specs-feup/lara/api/lara/Strings.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import Strings from "@specs-feup/lara/api/lara/Strings.ts"; import { BuiltinType, Call, @@ -7,8 +7,8 @@ import { FunctionJp, Statement, Type, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; export interface OpenClKernelReplacerConfiguration { kernelName: string; @@ -484,22 +484,40 @@ class Buffer { /* ------------------------------ ENUMS ----------------------------- */ -enum BufferKind { - INPUT = "CL_MEM_READ_ONLY", - OUTPUT = "CL_MEM_WRITE_ONLY", - INPUT_OUTPUT = "CL_MEM_READ_WRITE", -} - -enum DeviceType { - CL_DEVICE_TYPE_ALL = "CL_DEVICE_TYPE_ALL", - CL_DEVICE_TYPE_CPU = "CL_DEVICE_TYPE_CPU", - CL_DEVICE_TYPE_GPU = "CL_DEVICE_TYPE_GPU", - CL_DEVICE_TYPE_ACCELERATOR = "CL_DEVICE_TYPE_ACCELERATOR", - CL_DEVICE_TYPE_DEFAULT = "CL_DEVICE_TYPE_DEFAULT", -} - -enum ErrorHandling { - EXIT = 0, - RETURN = 1, - USER = 2, -} +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +const BufferKind = { + INPUT: "CL_MEM_READ_ONLY", + OUTPUT: "CL_MEM_WRITE_ONLY", + INPUT_OUTPUT: "CL_MEM_READ_WRITE", +} as const; +type BufferKind = typeof BufferKind[keyof typeof BufferKind]; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +const DeviceType = { + CL_DEVICE_TYPE_ALL: "CL_DEVICE_TYPE_ALL", + CL_DEVICE_TYPE_CPU: "CL_DEVICE_TYPE_CPU", + CL_DEVICE_TYPE_GPU: "CL_DEVICE_TYPE_GPU", + CL_DEVICE_TYPE_ACCELERATOR: "CL_DEVICE_TYPE_ACCELERATOR", + CL_DEVICE_TYPE_DEFAULT: "CL_DEVICE_TYPE_DEFAULT", +} as const; +type DeviceType = typeof DeviceType[keyof typeof DeviceType]; + +/** + * This is supposed to be an enum, but Node.js v25 does bot support TS' enums, only erasable-syntax. + * Revert to an enum when Node.js supports it, or when we move to a different engine that supports it. + * This and the "type" declaration below. + */ +const ErrorHandling = { + EXIT: 0, + RETURN: 1, + USER: 2, +} as const; +type ErrorHandling = typeof ErrorHandling[keyof typeof ErrorHandling]; diff --git a/Clava-JS/src-api/clava/opencl/KernelReplacerAuto.ts b/Clava-JS/api/clava/opencl/KernelReplacerAuto.ts similarity index 80% rename from Clava-JS/src-api/clava/opencl/KernelReplacerAuto.ts rename to Clava-JS/api/clava/opencl/KernelReplacerAuto.ts index fda9724da8..5e75dd15b1 100644 --- a/Clava-JS/src-api/clava/opencl/KernelReplacerAuto.ts +++ b/Clava-JS/api/clava/opencl/KernelReplacerAuto.ts @@ -1,10 +1,10 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import Strings from "@specs-feup/lara/api/lara/Strings.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { Call, FileJp, Pragma } from "../../Joinpoints.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import Strings from "@specs-feup/lara/api/lara/Strings.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { Call, FileJp, Pragma } from "../../Joinpoints.ts"; import KernelReplacer, { - OpenClKernelReplacerConfiguration, -} from "./KernelReplacer.js"; + type OpenClKernelReplacerConfiguration, +} from "./KernelReplacer.ts"; // This aspect can be included in a library, imported and // called by a user, since it needs no configuration/parameterization diff --git a/Clava-JS/src-api/clava/opencl/OpenCLCall.ts b/Clava-JS/api/clava/opencl/OpenCLCall.ts similarity index 92% rename from Clava-JS/src-api/clava/opencl/OpenCLCall.ts rename to Clava-JS/api/clava/opencl/OpenCLCall.ts index ee33f6d8c6..2fd5779552 100644 --- a/Clava-JS/src-api/clava/opencl/OpenCLCall.ts +++ b/Clava-JS/api/clava/opencl/OpenCLCall.ts @@ -1,8 +1,8 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import Platforms from "@specs-feup/lara/api/lara/Platforms.js"; -import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.js"; -import { Call, FileJp, FunctionJp } from "../../Joinpoints.js"; -import OpenCLCallVariables from "./OpenCLCallVariables.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import Platforms from "@specs-feup/lara/api/lara/Platforms.ts"; +import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.ts"; +import { Call, FileJp, FunctionJp } from "../../Joinpoints.ts"; +import OpenCLCallVariables from "./OpenCLCallVariables.ts"; export default class OpenCLCall { $kernel: FunctionJp | undefined = undefined; diff --git a/Clava-JS/src-api/clava/opencl/OpenCLCallVariables.ts b/Clava-JS/api/clava/opencl/OpenCLCallVariables.ts similarity index 100% rename from Clava-JS/src-api/clava/opencl/OpenCLCallVariables.ts rename to Clava-JS/api/clava/opencl/OpenCLCallVariables.ts diff --git a/Clava-JS/src-api/clava/opt/Inlining.ts b/Clava-JS/api/clava/opt/Inlining.ts similarity index 74% rename from Clava-JS/src-api/clava/opt/Inlining.ts rename to Clava-JS/api/clava/opt/Inlining.ts index 0815cd4b61..f1c113c539 100644 --- a/Clava-JS/src-api/clava/opt/Inlining.ts +++ b/Clava-JS/api/clava/opt/Inlining.ts @@ -1,8 +1,8 @@ -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { FunctionJp, Joinpoint } from "../../Joinpoints.js"; -import Inliner from "../code/Inliner.js"; -import NormalizeToSubset from "./NormalizeToSubset.js"; -import PrepareForInlining from "./PrepareForInlining.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { FunctionJp, Joinpoint } from "../../Joinpoints.ts"; +import Inliner from "../code/Inliner.ts"; +import NormalizeToSubset from "./NormalizeToSubset.ts"; +import PrepareForInlining from "./PrepareForInlining.ts"; /** * diff --git a/Clava-JS/src-api/clava/opt/NormalizeToSubset.ts b/Clava-JS/api/clava/opt/NormalizeToSubset.ts similarity index 67% rename from Clava-JS/src-api/clava/opt/NormalizeToSubset.ts rename to Clava-JS/api/clava/opt/NormalizeToSubset.ts index 9d190a9adc..e1745d90d2 100644 --- a/Clava-JS/src-api/clava/opt/NormalizeToSubset.ts +++ b/Clava-JS/api/clava/opt/NormalizeToSubset.ts @@ -1,14 +1,13 @@ -import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { BinaryOp, Joinpoint } from "../../Joinpoints.js"; -import SimplifyAssignment from "../code/SimplifyAssignment.js"; -import StatementDecomposer from "../code/StatementDecomposer.js"; -import DecomposeDeclStmt from "../pass/DecomposeDeclStmt.js"; -import DecomposeVarDeclarations from "../pass/DecomposeVarDeclarations.js"; -import LocalStaticToGlobal from "../pass/LocalStaticToGlobal.js"; -import SimplifyLoops from "../pass/SimplifyLoops.js"; -import SimplifyReturnStmts from "../pass/SimplifyReturnStmts.js"; -import SimplifySelectionStmts from "../pass/SimplifySelectionStmts.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { BinaryOp, Joinpoint } from "../../Joinpoints.ts"; +import SimplifyAssignment from "../code/SimplifyAssignment.ts"; +import StatementDecomposer from "../code/StatementDecomposer.ts"; +import DecomposeDeclStmt from "../pass/DecomposeDeclStmt.ts"; +import DecomposeVarDeclarations from "../pass/DecomposeVarDeclarations.ts"; +import LocalStaticToGlobal from "../pass/LocalStaticToGlobal.ts"; +import SimplifyLoops from "../pass/SimplifyLoops.ts"; +import SimplifyReturnStmts from "../pass/SimplifyReturnStmts.ts"; +import SimplifySelectionStmts from "../pass/SimplifySelectionStmts.ts"; /** * diff --git a/Clava-JS/api/clava/opt/PrepareForInlining.ts b/Clava-JS/api/clava/opt/PrepareForInlining.ts new file mode 100644 index 0000000000..8c504edc79 --- /dev/null +++ b/Clava-JS/api/clava/opt/PrepareForInlining.ts @@ -0,0 +1,8 @@ +import { FunctionJp } from "../../Joinpoints.ts"; +import RemoveShadowing from "../code/RemoveShadowing.ts"; +import SingleReturnFunction from "../pass/SingleReturnFunction.ts"; + +export default function PrepareForInlining($function: FunctionJp) { + new SingleReturnFunction().apply($function); + RemoveShadowing($function); +} diff --git a/Clava-JS/src-api/clava/parser/BatchParser.ts b/Clava-JS/api/clava/parser/BatchParser.ts similarity index 81% rename from Clava-JS/src-api/clava/parser/BatchParser.ts rename to Clava-JS/api/clava/parser/BatchParser.ts index 3b0a1f2da4..7abd05ce59 100644 --- a/Clava-JS/src-api/clava/parser/BatchParser.ts +++ b/Clava-JS/api/clava/parser/BatchParser.ts @@ -1,12 +1,12 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import Check from "@specs-feup/lara/api/lara/Check.js"; -import System from "@specs-feup/lara/api/lara/System.js"; -import Strings from "@specs-feup/lara/api/lara/Strings.js"; -import Clava from "../Clava.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import { ClavaException, FileJp } from "../../Joinpoints.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import Check from "@specs-feup/lara/api/lara/Check.ts"; +import System from "@specs-feup/lara/api/lara/System.ts"; +import Strings from "@specs-feup/lara/api/lara/Strings.ts"; +import Clava from "../Clava.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import { FileJp } from "../../Joinpoints.ts"; /** * Parses C/C++ files. @@ -71,27 +71,24 @@ export default class BatchParser { private rebuildFile($literalFile: FileJp) { let parsing: boolean | undefined = true; while (parsing) { - const $parsedFile = $literalFile.rebuildTry() as FileJp | ClavaException; - - // Check if it is a file - if ($parsedFile instanceof FileJp) { - return $parsedFile; + try { + return $literalFile.rebuild(); + } catch (e) { + // It is an exception + parsing = this.solveRebuildFile(e as Error, $literalFile); } - - // It is an exception - parsing = this.solveRebuildFile($parsedFile, $literalFile); } return undefined; } - private solveRebuildFile($exception: ClavaException, $literalFile: FileJp) { + private solveRebuildFile($exception: Error, $literalFile: FileJp) { // Get error message const message = $exception.message; // Check if correct type - if ($exception.exceptionType !== "ClavaParserException") { - throw $exception.exception; + if ($exception.name !== "ClavaParserException") { + throw $exception; } const lines = Strings.asLines(message); diff --git a/Clava-JS/src-api/clava/pass/DecomposeDeclStmt.ts b/Clava-JS/api/clava/pass/DecomposeDeclStmt.ts similarity index 89% rename from Clava-JS/src-api/clava/pass/DecomposeDeclStmt.ts rename to Clava-JS/api/clava/pass/DecomposeDeclStmt.ts index 4835cbe815..f23aaae5c4 100644 --- a/Clava-JS/src-api/clava/pass/DecomposeDeclStmt.ts +++ b/Clava-JS/api/clava/pass/DecomposeDeclStmt.ts @@ -1,7 +1,7 @@ -import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; -import { DeclStmt, Joinpoint } from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; +import { DeclStmt, Joinpoint } from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; /** * Decomposes composite declaration statements into separate statements for each variable. diff --git a/Clava-JS/src-api/clava/pass/DecomposeVarDeclarations.ts b/Clava-JS/api/clava/pass/DecomposeVarDeclarations.ts similarity index 94% rename from Clava-JS/src-api/clava/pass/DecomposeVarDeclarations.ts rename to Clava-JS/api/clava/pass/DecomposeVarDeclarations.ts index d83cf5929a..46703b2d90 100644 --- a/Clava-JS/src-api/clava/pass/DecomposeVarDeclarations.ts +++ b/Clava-JS/api/clava/pass/DecomposeVarDeclarations.ts @@ -1,12 +1,12 @@ -import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; +import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; import { ArrayType, Joinpoint, UndefinedType, Vardecl, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; /** * Decomposes the vardecl nodes that are reachable from the given join point. diff --git a/Clava-JS/src-api/clava/pass/LocalStaticToGlobal.ts b/Clava-JS/api/clava/pass/LocalStaticToGlobal.ts similarity index 93% rename from Clava-JS/src-api/clava/pass/LocalStaticToGlobal.ts rename to Clava-JS/api/clava/pass/LocalStaticToGlobal.ts index d7663524d5..205e431aed 100644 --- a/Clava-JS/src-api/clava/pass/LocalStaticToGlobal.ts +++ b/Clava-JS/api/clava/pass/LocalStaticToGlobal.ts @@ -1,14 +1,14 @@ -import PassTransformationError from "@specs-feup/lara/api/lara/pass/PassTransformationError.js"; -import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; +import PassTransformationError from "@specs-feup/lara/api/lara/pass/PassTransformationError.ts"; +import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; import { DeclStmt, FunctionJp, Joinpoint, StorageClass, Vardecl, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; /** * Transforms local static variables into global variables. diff --git a/Clava-JS/src-api/clava/pass/SimplifyLoops.ts b/Clava-JS/api/clava/pass/SimplifyLoops.ts similarity index 80% rename from Clava-JS/src-api/clava/pass/SimplifyLoops.ts rename to Clava-JS/api/clava/pass/SimplifyLoops.ts index 5f68dccfd0..cdf38e7088 100644 --- a/Clava-JS/src-api/clava/pass/SimplifyLoops.ts +++ b/Clava-JS/api/clava/pass/SimplifyLoops.ts @@ -1,10 +1,10 @@ -import Pass from "@specs-feup/lara/api/lara/pass/Pass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; -import { DeclStmt, ExprStmt, Joinpoint, Loop } from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import DoToWhileStmt from "../code/DoToWhileStmt.js"; -import ForToWhileStmt from "../code/ForToWhileStmt.js"; -import StatementDecomposer from "../code/StatementDecomposer.js"; +import Pass from "@specs-feup/lara/api/lara/pass/Pass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; +import { DeclStmt, ExprStmt, Joinpoint, Loop, LoopKind } from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import DoToWhileStmt from "../code/DoToWhileStmt.ts"; +import ForToWhileStmt from "../code/ForToWhileStmt.ts"; +import StatementDecomposer from "../code/StatementDecomposer.ts"; export default class SimplifyLoops extends Pass { protected _name = "SimplifyLoops"; @@ -49,17 +49,17 @@ export default class SimplifyLoops extends Pass { } if ( $jp instanceof Loop && - ($jp.kind === "for" || $jp.kind === "dowhile" || $jp.kind === "while") + ($jp.kind === LoopKind.for || $jp.kind === LoopKind.dowhile || $jp.kind === LoopKind.while) ) { yield $jp; } } private makeWhileLoop($loop: Loop): Loop { - if ($loop.kind === "for") { + if ($loop.kind === LoopKind.for) { const $forToWhileScope = ForToWhileStmt($loop, this.label_suffix++); return $forToWhileScope.children[1] as Loop; - } else if ($loop.kind === "dowhile") { + } else if ($loop.kind === LoopKind.dowhile) { return DoToWhileStmt($loop, this.label_suffix++); } else { return $loop; diff --git a/Clava-JS/src-api/clava/pass/SimplifyReturnStmts.ts b/Clava-JS/api/clava/pass/SimplifyReturnStmts.ts similarity index 83% rename from Clava-JS/src-api/clava/pass/SimplifyReturnStmts.ts rename to Clava-JS/api/clava/pass/SimplifyReturnStmts.ts index d217f68a0d..c587d15467 100644 --- a/Clava-JS/src-api/clava/pass/SimplifyReturnStmts.ts +++ b/Clava-JS/api/clava/pass/SimplifyReturnStmts.ts @@ -1,8 +1,8 @@ -import Pass from "@specs-feup/lara/api/lara/pass/Pass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { Joinpoint, ReturnStmt } from "../../Joinpoints.js"; -import StatementDecomposer from "../code/StatementDecomposer.js"; +import Pass from "@specs-feup/lara/api/lara/pass/Pass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { Joinpoint, ReturnStmt } from "../../Joinpoints.ts"; +import StatementDecomposer from "../code/StatementDecomposer.ts"; // TODO: Refactor to use the SimplePass pattern export default class SimplifyReturnStmts extends Pass { diff --git a/Clava-JS/src-api/clava/pass/SimplifySelectionStmts.ts b/Clava-JS/api/clava/pass/SimplifySelectionStmts.ts similarity index 82% rename from Clava-JS/src-api/clava/pass/SimplifySelectionStmts.ts rename to Clava-JS/api/clava/pass/SimplifySelectionStmts.ts index 4f5d434c45..24c04f89d1 100644 --- a/Clava-JS/src-api/clava/pass/SimplifySelectionStmts.ts +++ b/Clava-JS/api/clava/pass/SimplifySelectionStmts.ts @@ -1,8 +1,8 @@ -import Pass from "@specs-feup/lara/api/lara/pass/Pass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import { If, Joinpoint } from "../../Joinpoints.js"; -import StatementDecomposer from "../code/StatementDecomposer.js"; +import Pass from "@specs-feup/lara/api/lara/pass/Pass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import { If, Joinpoint } from "../../Joinpoints.ts"; +import StatementDecomposer from "../code/StatementDecomposer.ts"; // TODO: Refactor to use the SimplePass pattern export default class SimplifySelectionStmts extends Pass { diff --git a/Clava-JS/src-api/clava/pass/SingleReturnFunction.ts b/Clava-JS/api/clava/pass/SingleReturnFunction.ts similarity index 91% rename from Clava-JS/src-api/clava/pass/SingleReturnFunction.ts rename to Clava-JS/api/clava/pass/SingleReturnFunction.ts index 3420317885..f3b892f932 100644 --- a/Clava-JS/src-api/clava/pass/SingleReturnFunction.ts +++ b/Clava-JS/api/clava/pass/SingleReturnFunction.ts @@ -1,15 +1,15 @@ -import Pass from "@specs-feup/lara/api/lara/pass/Pass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import Pass from "@specs-feup/lara/api/lara/pass/Pass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { BuiltinType, FunctionJp, Joinpoint, ReturnStmt, Vardecl, -} from "../../Joinpoints.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import DecomposeVarDeclarations from "./DecomposeVarDeclarations.js"; +} from "../../Joinpoints.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import DecomposeVarDeclarations from "./DecomposeVarDeclarations.ts"; export default class SingleReturnFunction extends Pass { protected _name = "SingleReturnFunctions"; diff --git a/Clava-JS/src-api/clava/pass/TransformSwitchToIf.ts b/Clava-JS/api/clava/pass/TransformSwitchToIf.ts similarity index 96% rename from Clava-JS/src-api/clava/pass/TransformSwitchToIf.ts rename to Clava-JS/api/clava/pass/TransformSwitchToIf.ts index 2201ce9991..6a4cd85534 100644 --- a/Clava-JS/src-api/clava/pass/TransformSwitchToIf.ts +++ b/Clava-JS/api/clava/pass/TransformSwitchToIf.ts @@ -1,17 +1,18 @@ -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.js"; -import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.js"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import SimplePass from "@specs-feup/lara/api/lara/pass/SimplePass.ts"; +import PassResult from "@specs-feup/lara/api/lara/pass/results/PassResult.ts"; import { Break, Case, GotoStmt, If, Joinpoint, + OpKind, Statement, Switch, -} from "../../Joinpoints.js"; -import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js"; +} from "../../Joinpoints.ts"; +import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.ts"; /** * Transforms a switch statement into an if statement. @@ -180,26 +181,26 @@ export default class TransformSwitchToIf extends SimplePass { let $ifCondition; if ($case.values.length == 1) $ifCondition = ClavaJoinPoints.binaryOp( - "==", + OpKind.eq, $switchCondition, $case.values[0], "boolean" ); else { const $binOpGE = ClavaJoinPoints.binaryOp( - ">=", + OpKind.ge, $switchCondition, $case.values[0], "boolean" ); const $binOpLE = ClavaJoinPoints.binaryOp( - "<=", + OpKind.le, $switchCondition, $case.values[1], "boolean" ); $ifCondition = ClavaJoinPoints.binaryOp( - "&&", + OpKind.l_and, $binOpGE, $binOpLE, "boolean" diff --git a/Clava-JS/src-api/clava/stats/OpsBlock.ts b/Clava-JS/api/clava/stats/OpsBlock.ts similarity index 87% rename from Clava-JS/src-api/clava/stats/OpsBlock.ts rename to Clava-JS/api/clava/stats/OpsBlock.ts index ee7380138e..1f121d23ef 100644 --- a/Clava-JS/src-api/clava/stats/OpsBlock.ts +++ b/Clava-JS/api/clava/stats/OpsBlock.ts @@ -1,4 +1,4 @@ -import OpsCost from "./OpsCost.js"; +import OpsCost from "./OpsCost.ts"; export default class OpsBlock { diff --git a/Clava-JS/src-api/clava/stats/OpsCost.ts b/Clava-JS/api/clava/stats/OpsCost.ts similarity index 100% rename from Clava-JS/src-api/clava/stats/OpsCost.ts rename to Clava-JS/api/clava/stats/OpsCost.ts diff --git a/Clava-JS/src-api/clava/stats/OpsCounter.ts b/Clava-JS/api/clava/stats/OpsCounter.ts similarity index 95% rename from Clava-JS/src-api/clava/stats/OpsCounter.ts rename to Clava-JS/api/clava/stats/OpsCounter.ts index 8d3eccaf7b..ba22221e17 100644 --- a/Clava-JS/src-api/clava/stats/OpsCounter.ts +++ b/Clava-JS/api/clava/stats/OpsCounter.ts @@ -1,8 +1,8 @@ -import ClavaJoinPoints from "../ClavaJoinPoints.js"; -import GlobalVariable from "../code/GlobalVariable.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.js"; -import Logger from "../../lara/code/Logger.js"; +import ClavaJoinPoints from "../ClavaJoinPoints.ts"; +import GlobalVariable from "../code/GlobalVariable.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.ts"; +import Logger from "../../lara/code/Logger.ts"; import { BuiltinType, Call, @@ -10,7 +10,7 @@ import { Joinpoint, Op, Type, -} from "../../Joinpoints.js"; +} from "../../Joinpoints.ts"; /** * Instruments an application so that it counts total operations in a region of code. diff --git a/Clava-JS/src-api/clava/stats/StaticOpsCounter.ts b/Clava-JS/api/clava/stats/StaticOpsCounter.ts similarity index 95% rename from Clava-JS/src-api/clava/stats/StaticOpsCounter.ts rename to Clava-JS/api/clava/stats/StaticOpsCounter.ts index afdf1fff75..e8842ffa25 100644 --- a/Clava-JS/src-api/clava/stats/StaticOpsCounter.ts +++ b/Clava-JS/api/clava/stats/StaticOpsCounter.ts @@ -1,21 +1,24 @@ -import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; +import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; import { BinaryOp, BuiltinType, Call, Expression, + ExpressionUse, FunctionJp, Joinpoint, Loop, + LoopKind, Op, + OpKind, Param, Statement, Type, Vardecl, Varref, -} from "../../Joinpoints.js"; -import OpsBlock from "./OpsBlock.js"; +} from "../../Joinpoints.ts"; +import OpsBlock from "./OpsBlock.ts"; export default class StaticOpsCounter { // Whitelist of ops @@ -105,7 +108,7 @@ export default class StaticOpsCounter { } if ($stmt instanceof Loop) { - if ($stmt.kind !== "for") { + if ($stmt.kind !== LoopKind.for) { console.log( `Ignoring loops that are not 'fors' (location ${$stmt.location}) for now` ); @@ -280,19 +283,19 @@ export default class StaticOpsCounter { for (const $ref of refs) { // Ignore - if ($ref.use === "read") { + if ($ref.use === ExpressionUse.read) { continue; } // Not supported yet - if ($ref.use === "readwrite") { + if ($ref.use === ExpressionUse.readwrite) { console.log("Readwrite not supported yet"); return undefined; } // Check if assignment const $refParent = $ref.parent as Op; - if ($refParent.kind !== "assign") { + if ($refParent.kind !== OpKind.assign) { console.log("Not supported when not an assignment"); return undefined; } diff --git a/Clava-JS/src-api/clava/util/ClavaDataStore.ts b/Clava-JS/api/clava/util/ClavaDataStore.ts similarity index 92% rename from Clava-JS/src-api/clava/util/ClavaDataStore.ts rename to Clava-JS/api/clava/util/ClavaDataStore.ts index 20e0d5b648..e8972a740f 100644 --- a/Clava-JS/src-api/clava/util/ClavaDataStore.ts +++ b/Clava-JS/api/clava/util/ClavaDataStore.ts @@ -1,11 +1,11 @@ -import WeaverDataStore from "@specs-feup/lara/api/weaver/util/WeaverDataStore.js"; -import ClavaJavaTypes from "../ClavaJavaTypes.js"; +import WeaverDataStore from "@specs-feup/lara/api/weaver/util/WeaverDataStore.ts"; +import ClavaJavaTypes from "../ClavaJavaTypes.ts"; import JavaTypes, { - JavaClasses, -} from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import Io from "@specs-feup/lara/api/lara/Io.js"; -import DataStore from "@specs-feup/lara/api/lara/util/DataStore.js"; -import { arrayFromArgs } from "@specs-feup/lara/api/lara/core/LaraCore.js"; + type JavaClasses, +} from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import DataStore from "@specs-feup/lara/api/lara/util/DataStore.ts"; +import { arrayFromArgs } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; /** * DataStore used in Clava. diff --git a/Clava-JS/src-api/clava/util/CodeInserter.ts b/Clava-JS/api/clava/util/CodeInserter.ts similarity index 93% rename from Clava-JS/src-api/clava/util/CodeInserter.ts rename to Clava-JS/api/clava/util/CodeInserter.ts index f37b0c912b..b3aa88a6b6 100644 --- a/Clava-JS/src-api/clava/util/CodeInserter.ts +++ b/Clava-JS/api/clava/util/CodeInserter.ts @@ -1,7 +1,7 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import LineInserter from "@specs-feup/lara/api/lara/util/LineInserter.js"; -import { FileJp } from "../../Joinpoints.js"; -import Clava from "../Clava.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import LineInserter from "@specs-feup/lara/api/lara/util/LineInserter.ts"; +import { FileJp } from "../../Joinpoints.ts"; +import Clava from "../Clava.ts"; /** * Writes the original code of the application, with the possibility of inserting new lines of code. diff --git a/Clava-JS/src-api/clava/util/FileIterator.ts b/Clava-JS/api/clava/util/FileIterator.ts similarity index 94% rename from Clava-JS/src-api/clava/util/FileIterator.ts rename to Clava-JS/api/clava/util/FileIterator.ts index 21267c0aa5..592fbf70ba 100644 --- a/Clava-JS/src-api/clava/util/FileIterator.ts +++ b/Clava-JS/api/clava/util/FileIterator.ts @@ -1,8 +1,8 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import { FileJp } from "../../Joinpoints.js"; -import Clava from "../Clava.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import { FileJp } from "../../Joinpoints.ts"; +import Clava from "../Clava.ts"; /** * Given a folder, collects sources in that folder, parses and returns one each time next() is called. diff --git a/Clava-JS/src-api/lara/benchmark/ClavaBenchmarkInstance.ts b/Clava-JS/api/lara/benchmark/ClavaBenchmarkInstance.ts similarity index 87% rename from Clava-JS/src-api/lara/benchmark/ClavaBenchmarkInstance.ts rename to Clava-JS/api/lara/benchmark/ClavaBenchmarkInstance.ts index 90fe37bcbf..66de5f2603 100644 --- a/Clava-JS/src-api/lara/benchmark/ClavaBenchmarkInstance.ts +++ b/Clava-JS/api/lara/benchmark/ClavaBenchmarkInstance.ts @@ -1,11 +1,11 @@ -import Io from "@specs-feup/lara/api/lara/Io.js"; -import BenchmarkInstance from "@specs-feup/lara/api/lara/benchmark/BenchmarkInstance.js"; -import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import Query from "@specs-feup/lara/api/weaver/Query.js"; -import Clava from "../..//clava/Clava.js"; -import { Pragma } from "../../Joinpoints.js"; -import CMaker from "../../clava/cmake/CMaker.js"; -import ClavaJoinPoints from "../../clava/ClavaJoinPoints.js"; +import Io from "@specs-feup/lara/api/lara/Io.ts"; +import BenchmarkInstance from "@specs-feup/lara/api/lara/benchmark/BenchmarkInstance.ts"; +import { type JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import Query from "@specs-feup/lara/api/weaver/Query.ts"; +import Clava from "../..//clava/Clava.ts"; +import { Pragma } from "../../Joinpoints.ts"; +import CMaker from "../../clava/cmake/CMaker.ts"; +import ClavaJoinPoints from "../../clava/ClavaJoinPoints.ts"; /** * Instance of a Clava benchmark. diff --git a/Clava-JS/src-api/lara/code/Energy.ts b/Clava-JS/api/lara/code/Energy.ts similarity index 86% rename from Clava-JS/src-api/lara/code/Energy.ts rename to Clava-JS/api/lara/code/Energy.ts index 4e74a4cfe2..02ce672fca 100644 --- a/Clava-JS/src-api/lara/code/Energy.ts +++ b/Clava-JS/api/lara/code/Energy.ts @@ -1,11 +1,12 @@ -import EnergyBase from "@specs-feup/lara/api/lara/code/EnergyBase.js"; +import EnergyBase from "@specs-feup/lara/api/lara/code/EnergyBase.ts"; -import Clava from "../../clava/Clava.js"; -import Logger from "./Logger.js"; +import Clava from "../../clava/Clava.ts"; +import Logger from "./Logger.ts"; -import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.js"; -import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.js"; -import { FileJp, Joinpoint } from "../../Joinpoints.js"; +import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.ts"; +import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.ts"; +import { FileJp, Joinpoint } from "../../Joinpoints.ts"; +import { InsertPosition } from "@specs-feup/lara/api/LaraJoinPoint.ts"; export default class Energy extends EnergyBase { /** @@ -59,7 +60,7 @@ export default class Energy extends EnergyBase { const codeBefore = Energy.energy_rapl_measure(energyVarStart); const codeAfter = Energy.energy_rapl_measure(energyVarEnd); - $start.insert("before", codeBefore); + $start.insert(InsertPosition.before, codeBefore); logger.append(prefix).appendLongLong(energyVarEnd + " - " + energyVarStart); if (this.printUnit) { @@ -67,7 +68,7 @@ export default class Energy extends EnergyBase { } logger.ln(); logger.log($end); - $end.insert("after", codeAfter); + $end.insert(InsertPosition.after, codeAfter); } private static energy_rapl_measure(energyVar: string): string { diff --git a/Clava-JS/src-api/lara/code/Logger.ts b/Clava-JS/api/lara/code/Logger.ts similarity index 97% rename from Clava-JS/src-api/lara/code/Logger.ts rename to Clava-JS/api/lara/code/Logger.ts index 59a1aaeba5..96544fe6c8 100644 --- a/Clava-JS/src-api/lara/code/Logger.ts +++ b/Clava-JS/api/lara/code/Logger.ts @@ -1,13 +1,14 @@ -import LoggerBase from "@specs-feup/lara/api/lara/code/LoggerBase.js"; -import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.js"; -import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.js"; +import LoggerBase from "@specs-feup/lara/api/lara/code/LoggerBase.ts"; +import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.ts"; +import PrintOnce from "@specs-feup/lara/api/lara/util/PrintOnce.ts"; import { Expression, FileJp, FunctionJp, Joinpoint, Scope, -} from "../../Joinpoints.js"; +} from "../../Joinpoints.ts"; +import { InsertPosition } from "@specs-feup/lara/api/LaraJoinPoint.ts"; export default class Logger extends LoggerBase { private _useSpecsLogger: boolean; @@ -280,7 +281,7 @@ export default class Logger extends LoggerBase { } _insertCode($jp: Joinpoint, insertBefore: boolean, code: string) { - const insertBeforeString = insertBefore ? "before" : "after"; + const insertBeforeString = insertBefore ? InsertPosition.before : InsertPosition.after; if (insertBefore) { $jp.insert(insertBeforeString, code); diff --git a/Clava-JS/src-api/lara/code/Timer.ts b/Clava-JS/api/lara/code/Timer.ts similarity index 97% rename from Clava-JS/src-api/lara/code/Timer.ts rename to Clava-JS/api/lara/code/Timer.ts index d224445929..a5bc93ee67 100644 --- a/Clava-JS/src-api/lara/code/Timer.ts +++ b/Clava-JS/api/lara/code/Timer.ts @@ -1,11 +1,11 @@ -import Platforms from "@specs-feup/lara/api/lara/Platforms.js"; -import TimerBase from "@specs-feup/lara/api/lara/code/TimerBase.js"; -import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.js"; -import { TimerUnit } from "@specs-feup/lara/api/lara/util/TimeUnits.js"; -import { FileJp, Joinpoint, Scope } from "../../Joinpoints.js"; -import Clava from "../../clava/Clava.js"; -import ClavaJoinPoints from "../../clava/ClavaJoinPoints.js"; -import Logger from "./Logger.js"; +import Platforms from "@specs-feup/lara/api/lara/Platforms.ts"; +import TimerBase from "@specs-feup/lara/api/lara/code/TimerBase.ts"; +import IdGenerator from "@specs-feup/lara/api/lara/util/IdGenerator.ts"; +import { TimerUnit } from "@specs-feup/lara/api/lara/util/TimeUnits.ts"; +import { FileJp, Joinpoint, Scope } from "../../Joinpoints.ts"; +import Clava from "../../clava/Clava.ts"; +import ClavaJoinPoints from "../../clava/ClavaJoinPoints.ts"; +import Logger from "./Logger.ts"; export default class Timer extends TimerBase { addedDefines: Set = new Set(); diff --git a/Clava-JS/src-api/lara/metrics/EnergyMetric.ts b/Clava-JS/api/lara/metrics/EnergyMetric.ts similarity index 82% rename from Clava-JS/src-api/lara/metrics/EnergyMetric.ts rename to Clava-JS/api/lara/metrics/EnergyMetric.ts index b049f001d1..ed14821d90 100644 --- a/Clava-JS/src-api/lara/metrics/EnergyMetric.ts +++ b/Clava-JS/api/lara/metrics/EnergyMetric.ts @@ -1,9 +1,9 @@ -import Strings from "@specs-feup/lara/api/lara/Strings.js"; -import Metric from "@specs-feup/lara/api/lara/metrics/Metric.js"; -import MetricResult from "@specs-feup/lara/api/lara/metrics/MetricResult.js"; -import ProcessExecutor from "@specs-feup/lara/api/lara/util/ProcessExecutor.js"; -import { Joinpoint } from "../../Joinpoints.js"; -import Energy from "../code/Energy.js"; +import Strings from "@specs-feup/lara/api/lara/Strings.ts"; +import Metric from "@specs-feup/lara/api/lara/metrics/Metric.ts"; +import MetricResult from "@specs-feup/lara/api/lara/metrics/MetricResult.ts"; +import ProcessExecutor from "@specs-feup/lara/api/lara/util/ProcessExecutor.ts"; +import { Joinpoint } from "../../Joinpoints.ts"; +import Energy from "../code/Energy.ts"; /** * Measures energy consumed during an application. diff --git a/Clava-JS/src-api/lara/metrics/ExecutionTimeMetric.ts b/Clava-JS/api/lara/metrics/ExecutionTimeMetric.ts similarity index 82% rename from Clava-JS/src-api/lara/metrics/ExecutionTimeMetric.ts rename to Clava-JS/api/lara/metrics/ExecutionTimeMetric.ts index 1fa7e319d4..055e7e0a5a 100644 --- a/Clava-JS/src-api/lara/metrics/ExecutionTimeMetric.ts +++ b/Clava-JS/api/lara/metrics/ExecutionTimeMetric.ts @@ -1,10 +1,10 @@ -import Strings from "@specs-feup/lara/api/lara/Strings.js"; -import Metric from "@specs-feup/lara/api/lara/metrics/Metric.js"; -import MetricResult from "@specs-feup/lara/api/lara/metrics/MetricResult.js"; -import ProcessExecutor from "@specs-feup/lara/api/lara/util/ProcessExecutor.js"; -import { TimerUnit } from "@specs-feup/lara/api/lara/util/TimeUnits.js"; -import { Joinpoint } from "../../Joinpoints.js"; -import Timer from "../code/Timer.js"; +import Strings from "@specs-feup/lara/api/lara/Strings.ts"; +import Metric from "@specs-feup/lara/api/lara/metrics/Metric.ts"; +import MetricResult from "@specs-feup/lara/api/lara/metrics/MetricResult.ts"; +import ProcessExecutor from "@specs-feup/lara/api/lara/util/ProcessExecutor.ts"; +import { TimerUnit } from "@specs-feup/lara/api/lara/util/TimeUnits.ts"; +import { Joinpoint } from "../../Joinpoints.ts"; +import Timer from "../code/Timer.ts"; /** * Measures execution time of an application. diff --git a/Clava-JS/src-api/weaver/WeaverLauncher.ts b/Clava-JS/api/weaver/WeaverLauncher.ts similarity index 77% rename from Clava-JS/src-api/weaver/WeaverLauncher.ts rename to Clava-JS/api/weaver/WeaverLauncher.ts index 1faee2abae..dc7587324c 100644 --- a/Clava-JS/src-api/weaver/WeaverLauncher.ts +++ b/Clava-JS/api/weaver/WeaverLauncher.ts @@ -1,5 +1,5 @@ -import WeaverLauncherBase from "@specs-feup/lara/api/weaver/WeaverLauncherBase.js"; -import Clava from "../clava/Clava.js"; +import WeaverLauncherBase from "@specs-feup/lara/api/weaver/WeaverLauncherBase.ts"; +import Clava from "../clava/Clava.ts"; export default class WeaverLauncher extends WeaverLauncherBase { execute(args: string | any[]) { diff --git a/Clava-JS/src-code/ClangPlugin/ClangPlugin.test.ts b/Clava-JS/code/ClangPlugin/ClangPlugin.test.ts similarity index 93% rename from Clava-JS/src-code/ClangPlugin/ClangPlugin.test.ts rename to Clava-JS/code/ClangPlugin/ClangPlugin.test.ts index 4eabe5a4b9..cea1531967 100644 --- a/Clava-JS/src-code/ClangPlugin/ClangPlugin.test.ts +++ b/Clava-JS/code/ClangPlugin/ClangPlugin.test.ts @@ -1,8 +1,8 @@ -import { jest } from "@jest/globals"; +import { vi } from "vitest"; import fs from "fs"; import path from "path"; -import ClangPlugin from "./ClangPlugin.js"; +import ClangPlugin from "./ClangPlugin.ts"; describe("ClangPlugin", () => { describe("validateClangExecutable", () => { @@ -76,17 +76,17 @@ describe("ClangPlugin", () => { const actualMap = await ClangPlugin.getAvailablePlugins(); expect(actualMap).toEqual(expectedMap); - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); it("should throw an error when the clang-plugin-binaries directory does not exist", async () => { - jest.spyOn(fs, "existsSync").mockClear().mockReturnValue(false); + vi.spyOn(fs, "existsSync").mockClear().mockReturnValue(false); await expect(ClangPlugin.getAvailablePlugins()).rejects.toThrow( "Could not find 'clang-plugin-binaries' directory" ); - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); }); */ diff --git a/Clava-JS/src-code/ClangPlugin/ClangPlugin.ts b/Clava-JS/code/ClangPlugin/ClangPlugin.ts similarity index 99% rename from Clava-JS/src-code/ClangPlugin/ClangPlugin.ts rename to Clava-JS/code/ClangPlugin/ClangPlugin.ts index 7ca3bdfd2b..4dc0c00abf 100644 --- a/Clava-JS/src-code/ClangPlugin/ClangPlugin.ts +++ b/Clava-JS/code/ClangPlugin/ClangPlugin.ts @@ -1,6 +1,6 @@ import fs from "fs"; import path from "path"; -import Sandbox from "../Sandbox.js"; +import Sandbox from "../Sandbox.ts"; import { fileURLToPath } from "url"; export default class ClangPlugin { diff --git a/Clava-JS/src-code/Dumper/AbstractDumper.ts b/Clava-JS/code/Dumper/AbstractDumper.ts similarity index 100% rename from Clava-JS/src-code/Dumper/AbstractDumper.ts rename to Clava-JS/code/Dumper/AbstractDumper.ts diff --git a/Clava-JS/src-code/Dumper/ClangJSONDumper.ts b/Clava-JS/code/Dumper/ClangJSONDumper.ts similarity index 92% rename from Clava-JS/src-code/Dumper/ClangJSONDumper.ts rename to Clava-JS/code/Dumper/ClangJSONDumper.ts index 1c7c0cf593..0808680984 100644 --- a/Clava-JS/src-code/Dumper/ClangJSONDumper.ts +++ b/Clava-JS/code/Dumper/ClangJSONDumper.ts @@ -1,4 +1,4 @@ -import AbstractDumper from "./AbstractDumper.js"; +import type AbstractDumper from "./AbstractDumper.ts"; import { spawn } from "child_process"; diff --git a/Clava-JS/src-code/Sandbox.test.ts b/Clava-JS/code/Sandbox.test.ts similarity index 98% rename from Clava-JS/src-code/Sandbox.test.ts rename to Clava-JS/code/Sandbox.test.ts index e05dcc03a6..5e49d52cb9 100644 --- a/Clava-JS/src-code/Sandbox.test.ts +++ b/Clava-JS/code/Sandbox.test.ts @@ -1,4 +1,4 @@ -import Sandbox from "./Sandbox.js"; +import Sandbox from "./Sandbox.ts"; describe("Sandbox", () => { describe("sanitizeCommand", () => { diff --git a/Clava-JS/src-code/Sandbox.ts b/Clava-JS/code/Sandbox.ts similarity index 99% rename from Clava-JS/src-code/Sandbox.ts rename to Clava-JS/code/Sandbox.ts index 50b423cf0a..5025f5803c 100644 --- a/Clava-JS/src-code/Sandbox.ts +++ b/Clava-JS/code/Sandbox.ts @@ -1,5 +1,5 @@ import { ChildProcess, spawn, spawnSync } from "child_process"; -import { addActiveChildProcess } from "@specs-feup/lara/code/ChildProcessHandling.js"; +import { addActiveChildProcess } from "@specs-feup/lara/code/ChildProcessHandling.ts"; export default class Sandbox { /** diff --git a/Clava-JS/src-code/WeaverConfiguration.ts b/Clava-JS/code/WeaverConfiguration.ts similarity index 58% rename from Clava-JS/src-code/WeaverConfiguration.ts rename to Clava-JS/code/WeaverConfiguration.ts index aa00ea44ab..f003327e0c 100644 --- a/Clava-JS/src-code/WeaverConfiguration.ts +++ b/Clava-JS/code/WeaverConfiguration.ts @@ -1,15 +1,15 @@ -import WeaverConfiguration from "@specs-feup/lara/code/WeaverConfiguration.js"; +import type WeaverConfiguration from "@specs-feup/lara/code/WeaverConfiguration.ts"; import path from "path"; import { fileURLToPath } from "url"; export const weaverConfig: WeaverConfiguration = { weaverName: "clava", weaverPrettyName: "Clava", - weaverFileName: "@specs-feup/lara/code/Weaver.js", + weaverFileName: "@specs-feup/lara/code/Weaver.ts", jarPath: path.join( path.dirname(path.dirname(fileURLToPath(import.meta.url))), "./java-binaries/" ), javaWeaverQualifiedName: "pt.up.fe.specs.clava.weaver.CxxWeaver", - importForSideEffects: ["@specs-feup/clava/api/Joinpoints.js", "@specs-feup/clava/code/sideEffects.js"], + importForSideEffects: ["@specs-feup/clava/api/Joinpoints.ts", "@specs-feup/clava/code/sideEffects.ts"], }; diff --git a/Clava-JS/src-code/index.ts b/Clava-JS/code/index.ts old mode 100644 new mode 100755 similarity index 73% rename from Clava-JS/src-code/index.ts rename to Clava-JS/code/index.ts index c9782c286c..bdf002b8a8 --- a/Clava-JS/src-code/index.ts +++ b/Clava-JS/code/index.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node -import WeaverLauncher from "@specs-feup/lara/code/WeaverLauncher.js"; -import { weaverConfig } from "./WeaverConfiguration.js"; +import WeaverLauncher from "@specs-feup/lara/code/WeaverLauncher.ts"; +import { weaverConfig } from "./WeaverConfiguration.ts"; const weaverLauncher = new WeaverLauncher(weaverConfig); diff --git a/Clava-JS/src-code/sideEffects.ts b/Clava-JS/code/sideEffects.ts similarity index 77% rename from Clava-JS/src-code/sideEffects.ts rename to Clava-JS/code/sideEffects.ts index c62eac57fa..090da8743b 100644 --- a/Clava-JS/src-code/sideEffects.ts +++ b/Clava-JS/code/sideEffects.ts @@ -1,5 +1,5 @@ -import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.js"; -import Weaver from "@specs-feup/lara/api/weaver/Weaver.js"; +import JavaTypes from "@specs-feup/lara/api/lara/util/JavaTypes.ts"; +import Weaver from "@specs-feup/lara/api/weaver/Weaver.ts"; import path from "node:path"; import os from "node:os"; @@ -18,14 +18,14 @@ const datastore = Weaver.getWeaverEngine().getData().get(); datastore.set(CxxWeaverOptions.DISABLE_CLAVA_INFO, true); datastore.set( CodeParser.DUMPER_FOLDER, - new JavaTypes.File(getVersionedCacheDir()) + new JavaTypes.File(getClavaCacheDir()) ); /** Code to obtain temporary folder **/ -function getVersionedCacheDir(): string { - // Use name+version to isolate different installed versions - return path.join(getCacheBaseDir(), pkg.name, pkg.version); +function getClavaCacheDir(): string { + // Java adds separate namespaces for the dumper and CUDA resources. + return path.join(getCacheBaseDir(), pkg.name); } function getCacheBaseDir(): string { diff --git a/Clava-JS/eslint.config.js b/Clava-JS/eslint.config.js deleted file mode 100644 index 2273574c58..0000000000 --- a/Clava-JS/eslint.config.js +++ /dev/null @@ -1,58 +0,0 @@ -import { fileURLToPath } from "url"; -import { dirname } from "path"; -import typescriptEslint from "typescript-eslint"; -import tsdoc from "eslint-plugin-tsdoc"; -import jest from "eslint-plugin-jest"; -import js from "@eslint/js"; -import eslintConfigPrettier from "eslint-config-prettier"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -export default [ - js.configs.recommended, - eslintConfigPrettier, - ...typescriptEslint.configs.recommended, - { - ignores: ["**/*.d.ts", "**/*.config.js"], - }, - { - plugins: { - "@typescript-eslint": typescriptEslint.plugin, - tsdoc, - }, - - languageOptions: { - parser: typescriptEslint.parser, - ecmaVersion: 5, - sourceType: "script", - - parserOptions: { - project: ["./*/tsconfig.json", "./tsconfig.*.json"], - tsconfigRootDir: __dirname, - }, - }, - - rules: { - "tsdoc/syntax": "warn", - }, - }, - { - ...typescriptEslint.configs.disableTypeChecked, - files: ["scripts/**/*.js"], - }, - { - ...jest.configs["flat/recommended"], - files: ["**/*.spec.ts", "**/*.test.ts"], - - plugins: { - jest, - }, - - languageOptions: { - globals: { - ...jest.environments.globals.globals, - }, - }, - }, -]; diff --git a/Clava-JS/jest.config.js b/Clava-JS/jest.config.js deleted file mode 100644 index ea4524bfa8..0000000000 --- a/Clava-JS/jest.config.js +++ /dev/null @@ -1,18 +0,0 @@ -const config = { - preset: "ts-jest/presets/default-esm", - testEnvironment: "node", - notify: true, - notifyMode: "always", - //verbose: true, - collectCoverage: false, - coverageDirectory: "coverage", - coverageReporters: ["text", "lcov"], - collectCoverageFrom: ["**/*[^.d].(t|j)s"], - coverageProvider: "v8", - moduleNameMapper: { - "(.+)\\.js": "$1", - }, - projects: ["src-api", "src-code"], -}; - -export default config; diff --git a/Clava-JS/jest/ClavaLegacyTester.ts b/Clava-JS/jest/ClavaLegacyTester.ts deleted file mode 100644 index c5a75e0ca1..0000000000 --- a/Clava-JS/jest/ClavaLegacyTester.ts +++ /dev/null @@ -1,44 +0,0 @@ -import ClavaJavaTypes, { - ClavaJavaClasses, -} from "@specs-feup/clava/api/clava/ClavaJavaTypes.js"; - -import { WeaverLegacyTester } from "@specs-feup/lara/jest/WeaverLegacyTester.js"; - -export class ClavaLegacyTester extends WeaverLegacyTester { - protected readonly WORK_FOLDER: string = "cxx_weaver_output"; - private readonly standard: ClavaJavaClasses.Standard; - private readonly compilerFlags: string; - - public constructor( - basePackage: string, - standard: ClavaJavaClasses.Standard, - compilerFlags: string = "" - ) { - super(basePackage); - this.standard = standard; - this.compilerFlags = compilerFlags; - - this.set(ClavaJavaTypes.ClavaOptions.FLAGS, this.compilerFlags); - } - - public async test( - laraResource: string, - ...codeResources: string[] - ): Promise { - if (this.standard != null) { - this.set(ClavaJavaTypes.ClavaOptions.STANDARD, this.standard); - } - - this.set( - ClavaJavaTypes.CxxWeaverOption.CHECK_SYNTAX, - this.checkWovenCodeSyntax - ); - this.set(ClavaJavaTypes.CxxWeaverOption.DISABLE_CLAVA_INFO, true); - this.set(ClavaJavaTypes.CxxWeaverOption.DISABLE_CODE_GENERATION); - - // Enable parallel parsing - //this.set(ClavaJavaTypes.ParallelCodeParser.PARALLEL_PARSING); - - await super.test(laraResource, ...codeResources); - } -} diff --git a/Clava-JS/oxlint.config.ts b/Clava-JS/oxlint.config.ts new file mode 100644 index 0000000000..2f6883cbde --- /dev/null +++ b/Clava-JS/oxlint.config.ts @@ -0,0 +1,6 @@ +import config from "@specs-feup/lara/oxlint.config.ts"; +import { defineConfig } from "oxlint"; + +export default defineConfig({ + extends: [config], +}); diff --git a/Clava-JS/package.json b/Clava-JS/package.json index 1c253d8ed6..f0a50ffae2 100644 --- a/Clava-JS/package.json +++ b/Clava-JS/package.json @@ -3,38 +3,48 @@ "version": "3.5.1", "description": "A C/C++ source-to-source compiler written in Typescript", "type": "module", + "bin": { + "clava": "./code/index.ts" + }, + "exports": { + "./api/*.test.ts": null, + "./api/*.config.ts": null, + "./api/*.js": "./api/*.ts", + "./api/*": "./api/*.ts", + "./api/*.ts": "./api/*.ts", + "./code/*.test.ts": null, + "./code/*.config.ts": null, + "./code/*.js": "./code/*.ts", + "./code/*": "./code/*.ts", + "./code/*.ts": "./code/*.ts" + }, "files": [ "api", "code", - "src-api", - "src-code", "java-binaries", ".gitignore", - "eslint.config.js", - "jest.config.js", + "oxlint.config.ts", + "vitest.config.ts", "LICENSE", "package.json", "README.md", - "tsconfig.jest.json", "tsconfig.json", "typedoc.config.js" ], - "bin": { - "clava": "./code/index.js" - }, "scripts": { - "run": "node ./code/index.js", - "build": "tsc -b src-api src-code", - "build:api": "tsc -b src-api", - "build:code": "tsc -b src-code", + "run": "node ./code/index.ts", + "build": "tsc", "build:watch": "npm run build -- --watch", - "lint": "eslint .", - "test": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --detectOpenHandles --forceExit", - "test:api": "npm run test -- src-api", - "test:code": "npm run test -- src-code", + "lint": "oxlint .", + "format": "oxfmt .", + "format:check": "oxfmt --check .", + "prepack": "node --input-type=module --eval \"import { validateJavaBinaries } from '@specs-feup/lara/scripts/validateJavaBinaries.js'; validateJavaBinaries();\"", + "test": "vitest run", + "test:api": "npm run test -- api", + "test:code": "npm run test -- code", "test:cov": "npm run test -- --coverage", "test:watch": "npm run test -- --watch", - "build-interfaces": "npx lara-build-interfaces --input ../ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaver.json --lara @specs-feup/lara/LaraJoinPointSpecification.json --output src-api/Joinpoints.ts" + "build-interfaces": "lara-build-interfaces --input ../ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaver.json --lara @specs-feup/lara/LaraJoinPointSpecification.json --output api/Joinpoints.ts" }, "repository": { "type": "git", @@ -59,21 +69,15 @@ "cytoscape": "^3.33.1" }, "devDependencies": { - "@jest/globals": "^30.2.0", "@types/debug": "^4.1.12", "@types/java": "^0.9.6", - "@types/jest": "^30.0.0", - "@types/node": "^20.14.10", + "@types/node": "^25.0.0", "@types/yargs": "^17.0.35", - "cross-env": "^10.1.0", - "eslint": "^9.32.2", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-jest": "^29.12.1", + "@vitest/coverage-v8": "^4.1.10", "eslint-plugin-tsdoc": "^0.5.0", - "jest": "^30.2.0", - "node-notifier": "^10.0.1", - "ts-jest": "^29.4.6", - "typescript": "^5.9.3", - "typescript-eslint": "^8.52.0" + "oxfmt": "^0.59.0", + "oxlint": "^1.74.0", + "typescript": "^7.0.2", + "vitest": "^4.1.10" } } diff --git a/Clava-JS/src-api/clava/opt/PrepareForInlining.ts b/Clava-JS/src-api/clava/opt/PrepareForInlining.ts deleted file mode 100644 index 2ee5f63d11..0000000000 --- a/Clava-JS/src-api/clava/opt/PrepareForInlining.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { FunctionJp } from "../../Joinpoints.js"; -import RemoveShadowing from "../code/RemoveShadowing.js"; -import SingleReturnFunction from "../pass/SingleReturnFunction.js"; - -export default function PrepareForInlining($function: FunctionJp) { - new SingleReturnFunction().apply($function); - RemoveShadowing($function); -} diff --git a/Clava-JS/src-api/jest.config.js b/Clava-JS/src-api/jest.config.js deleted file mode 100644 index c5e1ae31c2..0000000000 --- a/Clava-JS/src-api/jest.config.js +++ /dev/null @@ -1,19 +0,0 @@ -import { weaverConfig } from "../code/WeaverConfiguration.js"; - -const config = { - preset: "ts-jest/presets/default-esm", - testEnvironment: "@specs-feup/lara/jest/jestEnvironment.js", - globalSetup: "@specs-feup/lara/jest/jestGlobalSetup.js", - globalTeardown: "@specs-feup/lara/jest/jestGlobalTeardown.js", - setupFiles: ["@specs-feup/lara/jest/setupFiles/sharedJavaModule.js"], - setupFilesAfterEnv: ["@specs-feup/lara/jest/setupFiles/importSideEffects.js"], - moduleNameMapper: { - "@specs-feup/clava/api/(.+).js": "@specs-feup/clava/src-api/$1", - "(.+)\\.js": "$1", - }, - testEnvironmentOptions: { - weaverConfig, - }, -}; - -export default config; diff --git a/Clava-JS/src-api/tsconfig.json b/Clava-JS/src-api/tsconfig.json deleted file mode 100644 index b03a6a89ec..0000000000 --- a/Clava-JS/src-api/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../api" - }, - "exclude": ["node_modules", "**/*.spec.ts", "**/*.test.ts"], - "references": [{ "path": "../src-code" }] -} diff --git a/Clava-JS/src-code/jest.config.js b/Clava-JS/src-code/jest.config.js deleted file mode 100644 index f8502043b2..0000000000 --- a/Clava-JS/src-code/jest.config.js +++ /dev/null @@ -1,9 +0,0 @@ -const config = { - preset: "ts-jest/presets/default-esm", - testEnvironment: "node", - moduleNameMapper: { - "(.+)\\.js": "$1", - }, -}; - -export default config; diff --git a/Clava-JS/src-code/tsconfig.json b/Clava-JS/src-code/tsconfig.json deleted file mode 100644 index 8061f3caf7..0000000000 --- a/Clava-JS/src-code/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../code", - "composite": true - }, - "exclude": ["node_modules", "**/*.spec.ts", "**/*.test.ts"] -} diff --git a/Clava-JS/tsconfig.jest.json b/Clava-JS/tsconfig.jest.json deleted file mode 100644 index dd7eedda34..0000000000 --- a/Clava-JS/tsconfig.jest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": ["**/*.spec.ts", "**/*.test.ts"], - "exclude": ["node_modules"] -} diff --git a/Clava-JS/tsconfig.json b/Clava-JS/tsconfig.json index c05308dc10..416c109338 100644 --- a/Clava-JS/tsconfig.json +++ b/Clava-JS/tsconfig.json @@ -1,15 +1,14 @@ { "compilerOptions": { + "noEmit": true, "module": "NodeNext", - "moduleResolution": "NodeNext", - "isolatedModules": true, "declaration": true, "strict": true, - //"allowJs": true, - //"checkJs": true, - "sourceMap": true, - "declarationMap": true, - "allowSyntheticDefaultImports": true - //"esModuleInterop": true + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "types": ["node", "vitest/globals"], + "rewriteRelativeImportExtensions": true, + "erasableSyntaxOnly": true, + "verbatimModuleSyntax": true } } diff --git a/Clava-JS/typedoc.config.js b/Clava-JS/typedoc.config.js index b000de5443..357b6153bc 100644 --- a/Clava-JS/typedoc.config.js +++ b/Clava-JS/typedoc.config.js @@ -4,6 +4,6 @@ export default { extends: [ fileURLToPath(import.meta.resolve("@specs-feup/lara/typedoc.base.json")), ], - entryPoints: ["src-api/"], - tsconfig: "src-api/tsconfig.json", + entryPoints: ["api/"], + tsconfig: "tsconfig.json", }; diff --git a/Clava-JS/vitest.config.ts b/Clava-JS/vitest.config.ts new file mode 100644 index 0000000000..dd321932fb --- /dev/null +++ b/Clava-JS/vitest.config.ts @@ -0,0 +1,6 @@ +import { createWeaverVitestConfig } from "@specs-feup/lara/vitest/weaverVitestConfig.ts"; +import { weaverConfig } from "./code/WeaverConfiguration.ts"; + +export default createWeaverVitestConfig(weaverConfig, { + javaOptionsEnvironmentVariable: "CLAVA_JS_JAVA_OPTIONS", +}); diff --git a/Clava-JS/vitest/ClavaLegacyTester.ts b/Clava-JS/vitest/ClavaLegacyTester.ts new file mode 100644 index 0000000000..3b038339e5 --- /dev/null +++ b/Clava-JS/vitest/ClavaLegacyTester.ts @@ -0,0 +1,44 @@ +import ClavaJavaTypes, { + type ClavaJavaClasses, +} from "../api/clava/ClavaJavaTypes.ts"; + +import { WeaverLegacyTester } from "@specs-feup/lara/vitest/WeaverLegacyTester.ts"; + +export class ClavaLegacyTester extends WeaverLegacyTester { + protected readonly WORK_FOLDER: string = "cxx_weaver_output"; + private readonly standard: ClavaJavaClasses.Standard; + private readonly compilerFlags: string; + + public constructor( + basePackage: string, + standard: ClavaJavaClasses.Standard, + compilerFlags: string = "", + ) { + super(basePackage); + this.standard = standard; + this.compilerFlags = compilerFlags; + + this.set(ClavaJavaTypes.ClavaOptions.FLAGS, this.compilerFlags); + } + + public async test( + laraResource: string, + ...codeResources: string[] + ): Promise { + if (this.standard != null) { + this.set(ClavaJavaTypes.ClavaOptions.STANDARD, this.standard); + } + + this.set( + ClavaJavaTypes.CxxWeaverOption.CHECK_SYNTAX, + this.checkWovenCodeSyntax, + ); + this.set(ClavaJavaTypes.CxxWeaverOption.DISABLE_CLAVA_INFO, true); + this.set(ClavaJavaTypes.CxxWeaverOption.DISABLE_CODE_GENERATION); + + // Enable parallel parsing + //this.set(ClavaJavaTypes.ParallelCodeParser.PARALLEL_PARSING); + + await super.test(laraResource, ...codeResources); + } +} diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/attr/enums/AttributeKind.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/attr/enums/AttributeKind.java index 8158847f4a..5b0e3d7e71 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/attr/enums/AttributeKind.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/attr/enums/AttributeKind.java @@ -24,12 +24,19 @@ import pt.up.fe.specs.util.utilities.CachedItems; public enum AttributeKind implements StringProvider { - AddressSpace, AnnotateType, + ArmIn, + ArmInOut, ArmMveStrictPolymorphism, + ArmOut, + ArmPreserves, + ArmStreaming, + ArmStreamingCompatible, BTFTypeTag, CmseNSCall, + HLSLGroupSharedAddressSpace, + HLSLParamModifier, NoDeref, ObjCGC, ObjCInertUnsafeUnretained, @@ -49,15 +56,17 @@ public enum AttributeKind implements StringProvider { TypeNullable, TypeNullableResult, UPtr, + WebAssemblyFuncref, + CodeAlign, FallThrough, Likely, MustTail, OpenCLUnrollHint, - Suppress, Unlikely, AlwaysInline, NoInline, NoMerge, + Suppress, AArch64SVEPcs, AArch64VectorPcs, AMDGPUKernelCall, @@ -67,6 +76,7 @@ public enum AttributeKind implements StringProvider { FastCall, IntelOclBicc, LifetimeBound, + M68kRTD, MSABI, NSReturnsRetained, ObjCOwnership, @@ -94,6 +104,8 @@ public enum AttributeKind implements StringProvider { PassObjectSize, ReleaseHandle, UseHandle, + HLSLSV_DispatchThreadID, + HLSLSV_GroupIndex, AMDGPUFlatWorkGroupSize, AMDGPUNumSGPR, AMDGPUNumVGPR, @@ -116,6 +128,8 @@ public enum AttributeKind implements StringProvider { ArcWeakrefUnavailable, ArgumentWithTypeTag, ArmBuiltinAlias, + ArmLocallyStreaming, + ArmNew, Artificial, AsmLabel, AssertCapability, @@ -124,7 +138,9 @@ public enum AttributeKind implements StringProvider { AssumeAligned, Assumption, Availability, + AvailableOnlyInDefaultEvalMethod, BPFPreserveAccessIndex, + BPFPreserveStaticOffset, BTFDeclTag, Blocks, Builtin, @@ -153,6 +169,7 @@ public enum AttributeKind implements StringProvider { CapturedRecord, Cleanup, CmseNSEntry, + CodeModel, CodeSeg, Cold, Common, @@ -163,6 +180,12 @@ public enum AttributeKind implements StringProvider { ConsumableAutoCast, ConsumableSetOnRead, Convergent, + CoroDisableLifetimeBound, + CoroLifetimeBound, + CoroOnlyDestroyWhenComplete, + CoroReturnType, + CoroWrapper, + CountedBy, DLLExport, DLLExportStaticLocal, DLLImport, @@ -193,7 +216,8 @@ public enum AttributeKind implements StringProvider { GuardedVar, HIPManaged, HLSLNumThreads, - HLSLSV_GroupIndex, + HLSLResource, + HLSLResourceBinding, HLSLShader, Hot, IBAction, @@ -209,6 +233,7 @@ public enum AttributeKind implements StringProvider { M68kInterrupt, MIGServerRoutine, MSAllocator, + MSConstexpr, MSInheritance, MSNoVTable, MSP430Interrupt, @@ -216,6 +241,7 @@ public enum AttributeKind implements StringProvider { MSVtorDisp, MaxFieldAlignment, MayAlias, + MaybeUndef, MicroMips, MinSize, MinVectorWidth, @@ -227,6 +253,7 @@ public enum AttributeKind implements StringProvider { NSErrorDomain, NSReturnsAutoreleased, NSReturnsNotRetained, + NVPTXKernel, Naked, NoAlias, NoCommon, @@ -246,6 +273,7 @@ public enum AttributeKind implements StringProvider { NoThreadSafetyAnalysis, NoThrow, NoUniqueAddress, + NoUwtable, NotTailCalled, OMPAllocateDecl, OMPCaptureNoInit, @@ -288,11 +316,13 @@ public enum AttributeKind implements StringProvider { PragmaClangRodataSection, PragmaClangTextSection, PreferredName, + PreferredType, PtGuardedBy, PtGuardedVar, Pure, RISCVInterrupt, RandomizeLayout, + ReadOnlyPlacement, Reinitializes, ReleaseCapability, ReqdWorkGroupSize, @@ -313,6 +343,7 @@ public enum AttributeKind implements StringProvider { SpeculativeLoadHardening, StandaloneDebug, StrictFP, + StrictGuardStackCheck, SwiftAsync, SwiftAsyncError, SwiftAsyncName, @@ -320,12 +351,15 @@ public enum AttributeKind implements StringProvider { SwiftBridge, SwiftBridgedTypedef, SwiftError, + SwiftImportAsNonGeneric, + SwiftImportPropertyAsAccessors, SwiftName, SwiftNewType, SwiftPrivate, TLSModel, Target, TargetClones, + TargetVersion, TestTypestate, TransparentUnion, TrivialABI, @@ -334,6 +368,7 @@ public enum AttributeKind implements StringProvider { TypeVisibility, Unavailable, Uninitialized, + UnsafeBufferUsage, Unused, Used, UsingIfExists, @@ -382,6 +417,8 @@ public enum AttributeKind implements StringProvider { Overloadable, RenderScriptKernel, SwiftObjCMembers, + SwiftVersionedAddition, + SwiftVersionedRemoval, Thread, FirstAttr, LastAttr, @@ -398,7 +435,9 @@ public enum AttributeKind implements StringProvider { FirstInheritableParamAttr, LastInheritableParamAttr, FirstParameterABIAttr, - LastParameterABIAttr; + LastParameterABIAttr, + FirstHLSLAnnotationAttr, + LastHLSLAnnotationAttr; private static final Lazy> ENUM_HELPER = EnumHelperWithValue .newLazyHelperWithValue(AttributeKind.class); diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/VarDecl.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/VarDecl.java index 00a49dfd21..137e16b32f 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/VarDecl.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/VarDecl.java @@ -259,6 +259,10 @@ public void setStorageClass(String value) { set(STORAGE_CLASS, storageClass); } + public void setStorageClass(StorageClass storageClass) { + set(STORAGE_CLASS, storageClass); + } + @Override public SpecsList> getSignatureKeys() { return super.getSignatureKeys().andAdd(STORAGE_CLASS); diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/InitializationStyle.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/InitializationStyle.java index 21e3022c48..45a8b01f6e 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/InitializationStyle.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/InitializationStyle.java @@ -24,13 +24,15 @@ import pt.up.fe.specs.util.providers.StringProvider; public enum InitializationStyle implements StringProvider { - NO_INIT, CINIT, // C-style initialization with assignment + // Keep these explicit names for compatibility: build-interfaces exposes strings to TS, with no TS enum to convert + // them to. CALL_INIT("callinit"), // Call-style initialization (C++98) - LIST_INIT("listinit"); // Direct list-initialization (C++11) + LIST_INIT("listinit"), // Direct list-initialization (C++11) + ParenListInit; private static Lazy> ENUM_HELPER = EnumHelperWithValue - .newLazyHelperWithValue(InitializationStyle.class, NO_INIT); + .newLazyHelperWithValue(InitializationStyle.class); public static EnumHelperWithValue getHelper() { return ENUM_HELPER.get(); @@ -56,10 +58,10 @@ public String getCode(VarDecl node) { switch (this) { case CINIT: return cinitCode(node); - case NO_INIT: - return ""; case CALL_INIT: return callInitCode(node); + case ParenListInit: + return parenListInitCode(node); case LIST_INIT: return listInitCode(node); default: @@ -98,6 +100,16 @@ private String callInitCode(VarDecl node) { return "(" + init.getCode() + ")"; } + private String parenListInitCode(VarDecl node) { + Preconditions.checkArgument(node.getNumChildren() == 1, "Expected one child"); + ClavaNode init = node.getChild(0); + + Preconditions.checkArgument(init instanceof Expr, + "Expected an Expr, got '" + init.getClass().getSimpleName() + "'"); + + return init.getCode(); + } + private String listInitCode(VarDecl node) { // Must be present Expr initList = node.getInit().get(); @@ -111,4 +123,4 @@ private String listInitCode(VarDecl node) { // .orElseThrow(() -> new RuntimeException()); } -} \ No newline at end of file +} diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/Linkage.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/Linkage.java index 6ae4a3394d..f8c27a9319 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/Linkage.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/decl/enums/Linkage.java @@ -22,16 +22,17 @@ * */ public enum Linkage { + Invalid, /** * The entity is unique and can only be referred to from within its scope. */ - NoLinkage, + None, /** * the entity can be referred to from within the translation unit, but not other translation units. */ - InternalLinkage, + Internal, /** * External linkage within a unique namespace. @@ -41,30 +42,23 @@ public enum Linkage { * namespace, their names are unique to this translation unit, which is equivalent to having internal linkage from * the code-generation point of view. */ - UniqueExternalLinkage, + UniqueExternal, /** * No linkage according to the standard, but is visible from other translation units because of types defined in a * inline function. */ - VisibleNoLinkage, - - /** - * Internal linkage according to the Modules TS, but can be referred to from other translation units indirectly - * through inline functions and templates in the module interface. - * - */ - ModuleInternalLinkage, + VisibleNone, /** * Module linkage, which indicates that the entity can be referred to from other translation units within the same * module, and indirectly from arbitrary other translation units through inline functions and templates in the * module interface. */ - ModuleLinkage, + Module, /** * The entity can be referred to from other translation units. */ - ExternalLinkage; + External; } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/GenericJoinpoint.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/CXXParenListInitExpr.java similarity index 55% rename from ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/GenericJoinpoint.java rename to ClavaAst/src/pt/up/fe/specs/clava/ast/expr/CXXParenListInitExpr.java index 030cad1d79..92f93c195e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/GenericJoinpoint.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/CXXParenListInitExpr.java @@ -1,34 +1,30 @@ /** - * Copyright 2017 SPeCS. - * + * Copyright 2026 SPeCS. + *

    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + *

    * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package pt.up.fe.specs.clava.weaver.joinpoints; +package pt.up.fe.specs.clava.ast.expr; -import pt.up.fe.specs.clava.ClavaNode; -import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; +import java.util.Collection; -public class GenericJoinpoint extends ACxxWeaverJoinPoint { +import org.suikasoft.jOptions.Interfaces.DataStore; - private final ClavaNode node; +import pt.up.fe.specs.clava.ClavaNode; - public GenericJoinpoint(ClavaNode node, CxxWeaver weaver) { - super(weaver); - this.node = node; - } +/** + * A C++20 parenthesized list-initialization expression. + */ +public class CXXParenListInitExpr extends ParenListExpr { - @Override - public ClavaNode getNode() { - return node; + public CXXParenListInitExpr(DataStore data, Collection children) { + super(data, children); } - } diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/StringLiteral.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/StringLiteral.java index fc9b3f5569..8937042aee 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/StringLiteral.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/StringLiteral.java @@ -55,6 +55,12 @@ public StringLiteral(DataStore data, Collection children) { @Override public String getLiteral() { + // Unevaluated strings can contain source-level details, such as adjacent tokens separated by a line break, that + // are lost when using the evaluated byte payload. Keep Clang's validated source spelling. + if (get(STRING_KIND) == StringKind.UNEVALUATED) { + return super.getLiteral(); + } + // Update: Unfortunately it is not possible to blindly use the source code literal // For instance, if directives and macros appear in the middle of the literal, they will also appear in the // generated source code @@ -90,7 +96,7 @@ private String getStringFromBytes() { return SpecsStrings.escapeJson(new String(bytes, kind.getCharset())); } - // If ASCII, convert each byte directly + // Ordinary strings use one-byte characters; convert each byte directly. if (kind == StringKind.ORDINARY) { var literal = new StringBuilder(); diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/enums/StringKind.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/enums/StringKind.java index afdcfbb29b..8f141a1a51 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/enums/StringKind.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/expr/enums/StringKind.java @@ -18,12 +18,12 @@ import pt.up.fe.specs.util.exceptions.NotImplementedException; public enum StringKind { - ORDINARY, WIDE, UTF8(true), UTF16(true), - UTF32(true); + UTF32(true), + UNEVALUATED; private final boolean isUTF; @@ -47,6 +47,8 @@ public String getPrefix() { return "u"; case UTF32: return "U"; + case UNEVALUATED: + return ""; default: throw new NotImplementedException(this); } diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/extra/data/Language.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/extra/data/Language.java index b0a37b3991..d930ebb620 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/extra/data/Language.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/extra/data/Language.java @@ -70,6 +70,11 @@ public class Language extends ADataClass { */ public static final DataKey C_PLUS_PLUS_23 = KeyFactory.bool("c++23"); + /** + * True if is a C++26 variant (or later). + */ + public static final DataKey C_PLUS_PLUS_26 = KeyFactory.bool("c++26"); + /** * True if supports digraphs. */ diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/ElaboratedType.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/ElaboratedType.java index 0772dcacef..cb08094295 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/ElaboratedType.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/ElaboratedType.java @@ -63,7 +63,6 @@ public void setNamedType(Type namedType) { @Override public String getCode(ClavaNode sourceNode, String name) { - String code = getKeyword().getCode(); if (!code.isEmpty()) { code += " "; diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/UnaryTransformType.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/UnaryTransformType.java index 24c1773693..827d4bf60d 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/UnaryTransformType.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/UnaryTransformType.java @@ -14,6 +14,7 @@ package pt.up.fe.specs.clava.ast.type; import java.util.Collection; +import java.util.Optional; import org.suikasoft.jOptions.Datakey.DataKey; import org.suikasoft.jOptions.Datakey.KeyFactory; @@ -35,7 +36,11 @@ public class UnaryTransformType extends Type { public final static DataKey KIND = KeyFactory .enumeration("kind", UnaryTransformTypeKind.class); - public final static DataKey UNDERLYING_TYPE = KeyFactory.object("underlyingType", Type.class); + /** + * The transformed type, when Clang has resolved it. Dependent unary + * transforms can have no underlying type while still having a base type. + */ + public final static DataKey> UNDERLYING_TYPE = KeyFactory.optional("underlyingType"); public final static DataKey BASE_TYPE = KeyFactory.object("baseType", Type.class); @@ -49,7 +54,7 @@ public Type getBaseType() { return get(BASE_TYPE); } - public Type getUnderlyingType() { + public Optional getUnderlyingType() { return get(UNDERLYING_TYPE); } diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/CallingConvention.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/CallingConvention.java index b5f58e3af6..47d8f46fbc 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/CallingConvention.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/CallingConvention.java @@ -18,7 +18,6 @@ import pt.up.fe.specs.util.providers.StringProvider; public enum CallingConvention implements StringProvider { - C, X86StdCall, X86FastCall, @@ -39,7 +38,8 @@ public enum CallingConvention implements StringProvider { PreserveAll, AArch64VectorCall, AArch64SVEPCS, - AMDGPUKernelCall; + AMDGPUKernelCall, + M68kRTD; private static final Lazy> HELPER = EnumHelperWithValue .newLazyHelperWithValue(CallingConvention.class); diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/ElaboratedTypeKeyword.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/ElaboratedTypeKeyword.java index b9a3be4baa..3827d3650c 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/ElaboratedTypeKeyword.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/ElaboratedTypeKeyword.java @@ -19,13 +19,13 @@ import pt.up.fe.specs.util.providers.StringProvider; public enum ElaboratedTypeKeyword implements StringProvider { - STRUCT, - INTERFACE, - UNION, - CLASS, - ENUM, - TYPENAME, - NONE; + Struct, + Interface, + Union, + Class, + Enum, + Typename, + None; private static final Lazy> HELPER = EnumHelperWithValue .newLazyHelperWithValue(ElaboratedTypeKeyword.class); @@ -35,7 +35,7 @@ public static EnumHelperWithValue getHelper() { } public String getCode() { - if (this == NONE) { + if (this == None) { return ""; } @@ -46,4 +46,4 @@ public String getCode() { public String getString() { return SpecsStrings.toCamelCase(name()); } -} \ No newline at end of file +} diff --git a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/UnaryTransformTypeKind.java b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/UnaryTransformTypeKind.java index 920be2ab40..7710528a14 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/UnaryTransformTypeKind.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/ast/type/enums/UnaryTransformTypeKind.java @@ -14,8 +14,21 @@ package pt.up.fe.specs.clava.ast.type.enums; public enum UnaryTransformTypeKind { - + AddLvalueReference, + AddPointer, + AddRvalueReference, Decay, + MakeSigned, + MakeUnsigned, + RemoveAllExtents, + RemoveConst, + RemoveCV, + RemoveCVRef, + RemoveExtent, + RemovePointer, + RemoveReference, + RemoveRestrict, + RemoveVolatile, EnumUnderlyingType; } diff --git a/ClavaAst/src/pt/up/fe/specs/clava/language/Standard.java b/ClavaAst/src/pt/up/fe/specs/clava/language/Standard.java index f05370f1bb..b35aca2dda 100644 --- a/ClavaAst/src/pt/up/fe/specs/clava/language/Standard.java +++ b/ClavaAst/src/pt/up/fe/specs/clava/language/Standard.java @@ -33,21 +33,29 @@ public enum Standard implements StringProvider { C99, C11, C17, + C18, + C23, GNU90, GNU99, GNU11, GNU17, + GNU18, + GNU23, CXX98("c++98", true), CXX03("c++03", true), CXX11("c++11", true), CXX14("c++14", true), CXX17("c++17", true), - CXX2A("c++2a", true), + CXX20("c++20", true), + CXX23("c++23", true), + CXX26("c++26", true), GNUXX98("gnu++98", true), GNUXX11("gnu++11", true), GNUXX14("gnu++14", true), GNUXX17("gnu++17", true), - GNUXX2A("gnu++2a", true), + GNUXX20("gnu++20", true), + GNUXX23("gnu++23", true), + GNUXX26("gnu++26", true), OPENCL10("cl1.0"), OPENCL12("cl1.2"), OPENCL20("cl2.0"), @@ -63,8 +71,8 @@ public enum Standard implements StringProvider { private static final Lazy> ENUM_HELPER = EnumHelperWithValue .newLazyHelperWithValue(Standard.class); - private static final Set GNU_STANDARDS = SpecsCollections.asSet(GNU90, GNU99, GNU11, GNUXX98, GNUXX11, - GNUXX14); + private static final Set GNU_STANDARDS = SpecsCollections.asSet(GNU90, GNU99, GNU11, GNU17, GNU18, GNU23, + GNUXX98, GNUXX11, GNUXX14, GNUXX17, GNUXX20, GNUXX23, GNUXX26); public static EnumHelperWithValue getEnumHelper() { return ENUM_HELPER.get(); diff --git a/ClavaWeaver/.gitignore b/ClavaWeaver/.gitignore index 3ce57ad832..1170455d2e 100644 --- a/ClavaWeaver/.gitignore +++ b/ClavaWeaver/.gitignore @@ -2,7 +2,6 @@ cxx_weaver_output/ AutoParStats-default.json src/**/abstracts/ -!src/**/abstracts/ACxxWeaverJoinPoint.java src/**/exceptions/CxxWeaverException.java src/**/enums/ *.dotty diff --git a/ClavaWeaver/build.gradle b/ClavaWeaver/build.gradle index 687d2b6e97..91128a6e1c 100644 --- a/ClavaWeaver/build.gradle +++ b/ClavaWeaver/build.gradle @@ -11,7 +11,6 @@ java { withSourcesJar() } - // Repositories providers repositories { mavenCentral() @@ -21,11 +20,26 @@ configurations { weaverGeneratorRuntime } +// Project sources +sourceSets { + // Spec source set: compiled independently to avoid circular dependency + spec { + java { + srcDir 'src-spec' + } + } + main { + java { + srcDir 'src' + } + } +} + dependencies { implementation ":jOptions" implementation ":SpecsUtils" - implementation ":LanguageSpecification" + implementation ":LangSpec2" implementation ":LARAI" implementation ":LaraUtils" implementation ":WeaverInterface" @@ -37,33 +51,58 @@ dependencies { implementation 'com.google.guava:guava:33.4.0-jre' - weaverGeneratorRuntime ":WeaverGenerator" -} + weaverGeneratorRuntime ":WeaverGen2" -// Project sources -sourceSets { - main { - java { - srcDir 'src' - } - } + // Spec source set: only needs LangSpec2 and WeaverInterface (for BaseJoinPointSpec) + specImplementation ":LangSpec2" + specImplementation ":WeaverInterface" } -// Re-run the weaver generator +// Generate weaver abstracts using WeaverGen2 (Java DSL-based) tasks.register('generateWeaver', JavaExec) { group = "Execution" - description = "Generates the Weaver Abstracts" - classpath = configurations.weaverGeneratorRuntime - mainClass = 'org.lara.interpreter.weaver.generator.commandline.WeaverGenerator' + description = "Generates the Weaver Abstracts using WeaverGen2" + classpath = configurations.weaverGeneratorRuntime + sourceSets.spec.runtimeClasspath + mainClass = 'org.lara.weavergen2.cli.WeaverGen2Cli' args = [ - "-w", "CxxWeaver", - "-x", "./resources/clava/weaverspecs", - "-o", "./src", - "-p", "pt.up.fe.specs.clava.weaver", - "-n", "pt.up.fe.specs.clava.ClavaNode", - "-e", - "-j" + "pt.up.fe.specs.clava.weaver.CxxSpec", + "${projectDir}/src", + "--base", "org.lara.interpreter.weaver.interf.BaseJoinPointSpec", + "--node", "pt.up.fe.specs.clava.ClavaNode" ] } compileJava.dependsOn generateWeaver + +def clavaWeaverInstallDir = layout.buildDirectory.dir('install/ClavaWeaver') +def clavaJsJavaBinaries = layout.projectDirectory.dir('../Clava-JS/java-binaries') + +def syncClavaJsJavaBinaries = tasks.register('syncClavaJsJavaBinaries', Sync) { + group = 'distribution' + description = 'Synchronizes the ClavaWeaver installDist output used by Clava-JS.' + dependsOn tasks.named('installDist') + from clavaWeaverInstallDir + into clavaJsJavaBinaries + + // The destination is also used by npm packaging and must not retain files + // that are no longer part of installDist. + outputs.upToDateWhen { false } + + doFirst { + def installLib = clavaWeaverInstallDir.get().dir('lib').asFile + if (!installLib.isDirectory()) { + throw new GradleException("ClavaWeaver installDist output is missing: ${installLib}") + } + + def destination = clavaJsJavaBinaries.asFile.toPath() + if (java.nio.file.Files.isSymbolicLink(destination)) { + java.nio.file.Files.delete(destination) + } else if (java.nio.file.Files.exists(destination) && !java.nio.file.Files.isDirectory(destination)) { + throw new GradleException("Clava-JS java-binaries is not a directory: ${destination}") + } + } +} + +tasks.named('installDist') { + finalizedBy syncClavaJsJavaBinaries +} diff --git a/ClavaWeaver/resources/clava/test/issues/Issue_aiq_1.js b/ClavaWeaver/resources/clava/test/issues/Issue_aiq_1.js index 3bf6b2b675..068c79a804 100644 --- a/ClavaWeaver/resources/clava/test/issues/Issue_aiq_1.js +++ b/ClavaWeaver/resources/clava/test/issues/Issue_aiq_1.js @@ -1,7 +1,7 @@ import Query from "@specs-feup/lara/api/weaver/Query.js" -import {Loop} from "@specs-feup/clava/api/Joinpoints.js" +import { Loop, LoopKind } from "@specs-feup/clava/api/Joinpoints.js" -const forLoops = Query.search(Loop, (loop) => loop.kind === "for").get(); +const forLoops = Query.search(Loop, (loop) => loop.kind === LoopKind.for).get(); for (const forLoop of forLoops) { console.log("Cond: {\n" + forLoop.cond.code + "\n}\n"); diff --git a/ClavaWeaver/resources/clava/test/issues/c/results/Issue_aiq_1.js.txt b/ClavaWeaver/resources/clava/test/issues/c/results/Issue_aiq_1.js.txt index 742e8bff99..da1c2ce018 100644 --- a/ClavaWeaver/resources/clava/test/issues/c/results/Issue_aiq_1.js.txt +++ b/ClavaWeaver/resources/clava/test/issues/c/results/Issue_aiq_1.js.txt @@ -2,5 +2,5 @@ Cond: { i < len; } -lt +LT Found 1 forloops. \ No newline at end of file diff --git a/ClavaWeaver/resources/clava/test/weaver/Traversal.js b/ClavaWeaver/resources/clava/test/weaver/Traversal.js index 0b986a1259..9fb7b1278b 100644 --- a/ClavaWeaver/resources/clava/test/weaver/Traversal.js +++ b/ClavaWeaver/resources/clava/test/weaver/Traversal.js @@ -1,5 +1,5 @@ import Query from "@specs-feup/lara/api/weaver/Query.js"; -import TraversalType from "@specs-feup/lara/api/weaver/TraversalType.js"; +import { TraversalType } from "@specs-feup/lara/api/weaver/TraversalType.js"; for (const $jp of Query.search("function", "foo").search( undefined, diff --git a/ClavaWeaver/resources/clava/test/weaver/cpp/results/TypeTemplate.js.txt b/ClavaWeaver/resources/clava/test/weaver/cpp/results/TypeTemplate.js.txt index 3030db32df..18167a3213 100644 --- a/ClavaWeaver/resources/clava/test/weaver/cpp/results/TypeTemplate.js.txt +++ b/ClavaWeaver/resources/clava/test/weaver/cpp/results/TypeTemplate.js.txt @@ -10,4 +10,4 @@ Original template args: int,float After second arg to double: int,double After setting with array [double, int]: double,int After setting typedef_to_change: std::vector::const_iterator -After setting changed_typedef_type: std::vector::const_iterator \ No newline at end of file +After setting changed_typedef_type: std::vector::const_iterator diff --git a/ClavaWeaver/resources/clava/weaverspecs/actionModel.xml b/ClavaWeaver/resources/clava/weaverspecs/actionModel.xml deleted file mode 100644 index 2a555fea90..0000000000 --- a/ClavaWeaver/resources/clava/weaverspecs/actionModel.xml +++ /dev/null @@ -1,816 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ClavaWeaver/resources/clava/weaverspecs/artifacts.xml b/ClavaWeaver/resources/clava/weaverspecs/artifacts.xml deleted file mode 100644 index 538427b3ea..0000000000 --- a/ClavaWeaver/resources/clava/weaverspecs/artifacts.xml +++ /dev/null @@ -1,926 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ClavaWeaver/resources/clava/weaverspecs/joinPointModel.xml b/ClavaWeaver/resources/clava/weaverspecs/joinPointModel.xml deleted file mode 100644 index 0d53c11350..0000000000 --- a/ClavaWeaver/resources/clava/weaverspecs/joinPointModel.xml +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ClavaWeaver/settings.gradle b/ClavaWeaver/settings.gradle index 3c3e60e781..c743ff65f4 100644 --- a/ClavaWeaver/settings.gradle +++ b/ClavaWeaver/settings.gradle @@ -6,10 +6,10 @@ def laraFrameworkRoot = System.getenv('LARA_FRAMEWORK_HOME') ?: '../../lara-fram includeBuild("${specsJavaLibsRoot}/jOptions") includeBuild("${specsJavaLibsRoot}/SpecsUtils") -includeBuild("${laraFrameworkRoot}/LanguageSpecification") +includeBuild("${laraFrameworkRoot}/LangSpec2") includeBuild("${laraFrameworkRoot}/LARAI") includeBuild("${laraFrameworkRoot}/LaraUtils") -includeBuild("${laraFrameworkRoot}/WeaverGenerator") +includeBuild("${laraFrameworkRoot}/WeaverGen2") includeBuild("${laraFrameworkRoot}/WeaverInterface") includeBuild("../AntarexClavaApi") diff --git a/ClavaWeaver/src-spec/pt/up/fe/specs/clava/weaver/CxxSpec.java b/ClavaWeaver/src-spec/pt/up/fe/specs/clava/weaver/CxxSpec.java new file mode 100644 index 0000000000..c52766bf08 --- /dev/null +++ b/ClavaWeaver/src-spec/pt/up/fe/specs/clava/weaver/CxxSpec.java @@ -0,0 +1,1384 @@ +package pt.up.fe.specs.clava.weaver; + +import org.lara.langspec2.dsl.WeaverSpec; +import org.lara.langspec2.types.JpDataType.BoundKind; +import org.lara.langspec2.types.JpDataType.WildcardType; + +/** + * Weaver specification for the Clava C/C++ weaver, translated from the XML + * specification files + * (joinPointModel.xml and artifacts.xml) into the Java DSL. + */ +public class CxxSpec extends WeaverSpec { + + @Override + public void define() { + weaverPrefix("Cxx"); + packageName("pt.up.fe.specs.clava.weaver"); + rootJoinPoint("program"); + + // ===================================================================== + // Enum definitions + // ===================================================================== + + enumDef("StorageClass") + .value("NONE") + .value("AUTO") + .value("EXTERN") + .value("PRIVATE_EXTERN") + .value("REGISTER") + .value("STATIC") + .end(); + + enumDef("Relation") + .value("LE") + .value("LT") + .value("GE") + .value("GT") + .value("EQ") + .value("NE") + .end(); + + enumDef("LoopKind") + .value("for") + .value("while") + .value("dowhile") + .value("foreach") + .end(); + + enumDef("ExpressionUse") + .value("read") + .value("write") + .value("readwrite") + .end(); + + enumDef("OpKind") + .value("ptr_mem_d") + .value("ptr_mem_i") + .value("mul") + .value("div") + .value("rem") + .value("add") + .value("sub") + .value("shl") + .value("shr") + .value("cmp") + .value("lt") + .value("gt") + .value("le") + .value("ge") + .value("eq") + .value("ne") + .value("and") + .value("xor") + .value("or") + .value("l_and") + .value("l_or") + .value("assign") + .value("mul_assign") + .value("div_assign") + .value("rem_assign") + .value("add_assign") + .value("sub_assign") + .value("shl_assign") + .value("shr_assign") + .value("and_assign") + .value("xor_assign") + .value("or_assign") + .value("comma") + .value("post_inc") + .value("post_dec") + .value("pre_inc") + .value("pre_dec") + .value("addr_of") + .value("deref") + .value("plus") + .value("minus") + .value("not") + .value("l_not") + .value("real") + .value("imag") + .value("extension") + .value("cowait") + .value("ternary") + .end(); + + enumDef("WrapperStatementKind") + .value("comment") + .value("pragma") + .end(); + + // ===================================================================== + // Global attributes (weaver-specific, not in BaseJoinPointSpec) + // Excludes base contract: dump, joinPointType, node, self, super, + // children, descendants, scopeNodes, insert, toString, equals, instanceOf + // ===================================================================== + + global() + .attribute("root", jpRef("program"), "Returns the 'program' joinpoint at the root of the hierarchy") + .attribute("getAncestor") + .tooltip("Looks for an ancestor joinpoint name, walking back on the AST") + .param("type", STRING) + .returns(jpRef("joinpoint")) + .attribute("getDescendants") + .tooltip("Retrieves the descendants of the given type") + .param("type", STRING) + .returns(array(jpRef("joinpoint"))) + .attribute("getDescendantsAndSelf") + .tooltip("Retrieves the descendants of the given type, including the current joinpoint") + .param("type", STRING) + .returns(array(jpRef("joinpoint"))) + .attribute("getChainAncestor") + .tooltip("Looks for an ancestor joinpoint name, walking back on the joinpoint chain") + .param("type", STRING) + .returns(jpRef("joinpoint")) + .attribute("getAstAncestor") + .tooltip("[DEPRECATED: Looks for an ancestor AST name, walking back on the AST]") + .param("type", STRING) + .returns(jpRef("joinpoint")) + .attribute("contains") + .tooltip("Checks if the joinpoint contains the given joinpoint") + .param("jp", jpRef("joinpoint")) + .returns(BOOLEAN) + .attribute("hasParent", BOOLEAN) + .attribute("getFirstJp") + .tooltip("Retrieves the first node of the given type in the descendants") + .param("type", STRING) + .returns(jpRef("joinpoint")) + .attribute("endLine", INTEGER, "The ending line of the current node in the original code") + .attribute("endColumn", INTEGER, "The ending column of the current node in the original code") + .attribute("location", STRING, "A string with information about the file and code position of this node, if available") + .attribute("filename", STRING, "The filename of the current node") + .attribute("filepath", STRING, "The file path of the current node") + .attribute("astId", STRING, "The AST ID of the current node") + .attribute("ast", STRING, "String with a dump of the AST representation starting from this node. This representation corresponds to the internal Java representation of the ClavaAst, where the node names correspond to Java classes. To get an equivalent representation with join point names, use the attribute 'dump'") + .attribute("type", jpRef("type")) + .attribute("hasType", BOOLEAN, "True, if the join point has a type") + .attribute("bitWidth", INTEGER, "The bit width of the type returned by this join point, in relation to the definitions of its Translation Unit, or undefined if there is no type or bitwidth defined, or if the join point is not in a TranslationUnit") + .attribute("astName", STRING, "The name of the Java class of this node, which is similar to the equivalent node in Clang AST") + .attribute("astNumChildren", INT, "Returns the number of children of the node, considering null nodes") + .attribute("astChildren", array(jpRef("joinpoint")), "Returns an array with the children of the node, considering null nodes") + .attribute("getAstChild") + .tooltip("Returns the child of the node at the given index, considering null nodes") + .param("index", INT) + .returns(jpRef("joinpoint")) + .attribute("numChildren", INT, "Returns the number of children of the node, ignoring null nodes") + .attribute("getChild") + .tooltip("Returns the child of the node at the given index, ignoring null nodes") + .param("index", INT) + .returns(jpRef("joinpoint")) + .attribute("siblingsLeft", array(jpRef("joinpoint")), "Returns an array with the siblings that came before this node") + .attribute("siblingsRight", array(jpRef("joinpoint")), "Returns an array with the siblings that come after this node") + .attribute("leftJp", jpRef("joinpoint"), "Returns the node that came before this node, or undefined if there is none") + .attribute("rightJp", jpRef("joinpoint"), "Returns the node that comes after this node, or undefined if there is none") + .attribute("astIsInstance") + .tooltip("True, if this node is a Java instance of the given name, which corresponds to a simple Java class name of an AST node. For an equivalent function for join point names, use 'instanceOf(joinPointName)'") + .param("className", STRING) + .returns(BOOLEAN) + .attribute("hasNode") + .tooltip("True, if the given join point or AST node is the same (== test) as the current join point AST node") + .param("nodeOrJp", OBJECT) + .returns(BOOLEAN) + .attribute("chain", array(STRING), "String list of the names of the join points that form a path from the root to this node") + .attribute("javaFields", array(STRING), "[DEPRECATED: used attribute 'keys' instead, together with 'getValue'] The names of the Java fields of this node. Can be used as key of the attribute 'javaValue'") + .attribute("getJavaFieldType") + .tooltip("String with the full Java class name of the type of the Java field with the provided name") + .param("fieldName", STRING) + .returns(STRING) + .attribute("isInsideLoopHeader", BOOLEAN, "True, if the join point is inside a loop header (e.g., for, while)") + .attribute("isInsideHeader", BOOLEAN, "True, if the join point is inside a header (e.g., function declaration)") + .attribute("isInSystemHeader", BOOLEAN, "True, if the join point is inside a system header (e.g., #include )") + .attribute("getUserField") + .tooltip("Retrives values that have been associated to nodes of the AST with 'setUserField'") + .param("fieldName", STRING) + .returns(OBJECT) + .attribute("parentRegion", jpRef("joinpoint"), "Returns the parent region of this join point, or undefined if there is none") + .attribute("currentRegion", jpRef("joinpoint"), "Returns the current region of this join point") + .attribute("pragmas", array(jpRef("pragma")), "Returns the pragmas associated with this join point") + .attribute("data", OBJECT, "JS object associated with this node, containing parsed data of #pragma clava data when the node can be a target of pragmas. This is a special object, managed internally, and cannot be reassigned, to change its contents requires using key-value pairs. If the node can be the target of a pragma, the information stored in this object is persisted between rebuilds.") + .attribute("keys", array(STRING), "A list of the properties currently supported by this node. Can be used as parameter of the attribute 'getValue'") + .attribute("getValue") + .tooltip("Returns the value of the property with the given name") + .param("key", STRING) + .returns(OBJECT) + .attribute("getKeyType") + .tooltip("Returns the type of the property with the given name") + .param("key", STRING) + .returns(OBJECT) + .attribute("isMacro", BOOLEAN, "True if any descendant or the node itself was defined as a macro") + .attribute("firstChild", jpRef("joinpoint"), "Returns the first child of this node, or undefined if it has no child") + .attribute("lastChild", jpRef("joinpoint"), "Returns the last child of this node, or undefined if it has no child") + .attribute("hasChildren", BOOLEAN, "True if the node has any children") + .attribute("isCilk", BOOLEAN, "True if the node is a Cilk node") + .attribute("depth", INT, "Returns the depth of this node in the AST. Root=0") + .attribute("jpId", STRING, "Returns the ID of this join point. The ID is based on the position of the node in the code, and should remain stable between compilations (warning: only a few nodes - file, function, loop - currently support it)") + .attribute("stmt", jpRef("statement"), "Converts this join point to a statement, or returns undefined if it was not possible") + .attribute("inlineComments", array(jpRef("comment")), "Returns comments that are not explicitly in the AST, but embedded in other nodes") + .attribute("originNode", jpRef("joinpoint"), "If this join point was not originally from the parsed AST, returns the first join point of the original AST that contributed to its origin") + .attribute("jpFields") + .tooltip("List with the values of fields that are join points, recursively") + .param("recursive", BOOLEAN, "false") + .returns(array(jpRef("joinpoint"))) + .action("replaceWith") + .tooltip("Replaces this node with the given node") + .param("node", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("replaceWith") + .tooltip("Overload that accepts a string") + .param("node", STRING) + .returns(jpRef("joinpoint")) + .action("replaceWith") + .tooltip("Overload that accepts a list of joinpoints") + .param("node", array(jpRef("joinpoint"))) + .returns(jpRef("joinpoint")) + .action("replaceWithStrings") + .tooltip("Overload that accepts a list of strings") + .param("node", array(STRING)) + .returns(jpRef("joinpoint")) + .action("insertBefore") + .tooltip("Inserts the given joinpoint before this joinpoint") + .param("node", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("insertBefore") + .tooltip("Overload that accepts a string") + .param("node", STRING) + .returns(jpRef("joinpoint")) + .action("insertAfter") + .tooltip("Inserts the given joinpoint after this joinpoint") + .param("node", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("insertAfter") + .tooltip("Overload that accepts a string") + .param("node", STRING) + .returns(jpRef("joinpoint")) + .action("detach") + .tooltip("Removes the node associated to this joinpoint from the AST") + .returns(jpRef("joinpoint")) + .action("setType") + .tooltip("Sets the type of a node, if it has a type") + .param("type", jpRef("type")) + .returns(VOID) + .action("copy") + .tooltip("Performs a copy of the node and its children, but not of the nodes in its fields") + .returns(jpRef("joinpoint")) + .action("deepCopy") + .tooltip("Performs a copy of the node and its children, including the nodes in their fields (only the first level of field nodes, this function is not recursive)") + .returns(jpRef("joinpoint")) + .action("setUserField") + .tooltip("Associates arbitrary values to nodes of the AST") + .param("fieldName", STRING) + .param("value", OBJECT) + .returns(OBJECT) + .action("setUserField") + .tooltip("Overload that accepts a map") + .param("fieldNameAndValue", map(STRING, new WildcardType(BoundKind.UNBOUNDED, null))) + .returns(OBJECT) + .action("setValue") + .tooltip("Sets the value associated with the given property key") + .param("key", STRING) + .param("value", OBJECT) + .returns(jpRef("joinpoint")) + .action("messageToUser") + .tooltip("Adds a message that will be printed to the user after weaving finishes. Identical messages are removed") + .param("message", STRING) + .returns(VOID) + .action("removeChildren") + .tooltip("Removes the children of this node") + .returns(VOID) + .action("setFirstChild") + .tooltip("Replaces the first child, or inserts the join point if no child is present. Returns the replaced child, or undefined if there was no child present") + .param("node", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("setLastChild") + .tooltip("Replaces the last child, or inserts the join point if no child is present. Returns the replaced child, or undefined if there was no child present") + .param("node", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("toComment") + .tooltip("Replaces this join point with a comment with the same contents as .code") + .param("prefix", STRING, "\"\"") + .param("suffix", STRING, "\"\"") + .returns(jpRef("joinpoint")) + .action("setInlineComments") + .tooltip("Sets the comments that are embedded in a node") + .param("comments", array(STRING)) + .returns(VOID) + .action("setInlineComments") + .tooltip("Sets the comments that are embedded in a node") + .param("comments", STRING) + .returns(VOID) + .action("setData") + .tooltip("Setting data directly is not supported, this action just emits a warning and does nothing") + .param("source", OBJECT) + .returns(VOID) + .action("dataClear") + .tooltip("Clears all properties from the .data object") + .returns(VOID); + + // ===================================================================== + // Join point definitions + // ===================================================================== + + // --- Utility join points --- + + joinPoint("empty") + .tooltip("Utility joinpoint, to represent empty nodes when directly accessing the tree"); + + // --- Program / File --- + + joinPoint("program") + .tooltip("Represents the complete program and is the top-most joinpoint in the hierarchy") + .defaultAttribute("name") + .attribute("name", STRING) + .attribute("isCxx", BOOLEAN, "True if the program was compiled with a C++ standard") + .attribute("standard", STRING, "The name of the standard (e.g., c99, c++11)") + .attribute("stdFlag", STRING, "The flag of the standard (e.g., -std=c++11)") + .attribute("defaultFlags", array(STRING)) + .attribute("userFlags", array(STRING)) + .attribute("includeFolders", array(STRING)) + .attribute("baseFolder", STRING) + .attribute("weavingFolder", STRING) + .attribute("extraSources", array(STRING), "Paths to sources that the current program depends on") + .attribute("extraIncludes", array(STRING), "Paths to includes that the current program depends on") + .attribute("extraProjects", array(STRING), "Paths to folders of projects that the current program depends on") + .attribute("extraLibs", array(STRING), "Link libraries of external projects the current program depends on") + .attribute("main", jpRef("function"), "A function join point with the main function of the program, if one is available") + .attribute("files", array(jpRef("file")), "The files of the program") + .action("rebuild") + .tooltip("Recompiles the program currently represented by the AST, transforming literal code into AST nodes. Returns true if all files could be parsed correctly, or false otherwise") + .returns(BOOLEAN) + .action("rebuildFuzzy") + .tooltip("Similar to rebuild, but tries to fix compilation errors. Resulting program may not represent the originally intended functionality") + .returns(VOID) + .action("addFile") + .tooltip("Adds a file join point to the current program") + .param("file", jpRef("file")) + .returns(jpRef("joinpoint")) + .action("addFileFromPath") + .tooltip("Adds a file join point to the current program, from the given path, which can be either a Java File or a String") + .param("filepath", OBJECT) + .returns(jpRef("joinpoint")) + .action("push") + .tooltip("Creates a copy of the current AST and pushes it to the top of the AST stack") + .returns(VOID) + .action("pop") + .tooltip("Discards the AST at the top of the AST stack") + .returns(VOID) + .action("addExtraInclude") + .tooltip("Adds a path to an include that the current program depends on") + .param("path", STRING) + .returns(VOID) + .action("addExtraIncludeFromGit") + .tooltip("Adds a path based on a git repository to an include that the current program depends on") + .param("gitRepo", STRING) + .param("path", STRING, "null") + .returns(VOID) + .action("addExtraSource") + .tooltip("Adds a path to a source that the current program depends on") + .param("path", STRING) + .returns(VOID) + .action("addExtraSourceFromGit") + .tooltip("Adds a path based on a git repository to a source that the current program depends on") + .param("gitRepo", STRING) + .param("path", STRING, "null") + .returns(VOID) + .action("addProjectFromGit") + .tooltip("Adds a path based on a git repository to a project that the current program depends on") + .param("gitRepo", STRING) + .param("libs", array(STRING)) + .param("path", STRING, "null") + .returns(VOID) + .action("addExtraLib") + .tooltip("Adds a library (e.g., -pthreads) that the current program depends on") + .param("lib", STRING) + .returns(VOID) + .action("atexit") + .tooltip("Registers a function to be executed when the program exits") + .param("function", jpRef("function")) + .returns(VOID); + + joinPoint("file") + .tooltip("Represents a source file (.c, .cpp, .cl, etc)") + .defaultAttribute("name") + .attribute("name", STRING) + .attribute("file", OBJECT, "The Java File object associated with this file") + .attribute("hasMain", BOOLEAN, "True if this file has the main function as a descendant") + .attribute("path", STRING, "The folder path for this file") + .attribute("relativeFilepath", STRING, "The file path relative to the base folder of the program") + .attribute("relativeFolderpath", STRING, "The folder path relative to the base folder of the program") + .attribute("baseSourcePath", STRING, "The base source path for this file") + .attribute("isCxx", BOOLEAN, "True if this file is a being parsed as a C++ file") + .attribute("isHeader", BOOLEAN, "True if this file is a header file") + .attribute("isOpenCL", BOOLEAN, "True if this file is an OpenCL file") + .attribute("getDestinationFilepath") + .tooltip("The complete path to the file that will be generated by the weaver, given a destination folder") + .param("destinationFolderpath", STRING, "null") + .returns(STRING) + .attribute("sourceFoldername", STRING, "The name of the source folder of this file, or undefined if it has none") + .attribute("hasParsingErrors", BOOLEAN, "True if there were errors during the parsing of this file") + .attribute("errorOutput", STRING, "The error output produced during the parsing of this file, if any") + .attribute("includes", array(jpRef("include")), "The include directives in this file") + .action("addInclude") + .tooltip("Adds an include to the current file. If the file already has the include, it does nothing") + .param("name", STRING) + .param("isAngled", BOOLEAN, "false") + .returns(VOID) + .action("addIncludeJp") + .tooltip("Overload of addInclude which accepts a join point") + .param("jp", jpRef("joinpoint")) + .returns(VOID) + .action("addCInclude") + .tooltip("Adds a C include to the current file. If the file already has the include, it does nothing") + .param("name", STRING) + .param("isAngled", BOOLEAN, "false") + .returns(VOID) + .action("addGlobal") + .tooltip("Adds a global variable to this file") + .param("name", STRING) + .param("type", jpRef("joinpoint")) + .param("initValue", STRING) + .returns(jpRef("vardecl")) + .action("write") + .tooltip("Writes the code of this file to a given folder") + .param("destinationFoldername", STRING) + .returns(STRING) + .action("setName") + .tooltip("Changes the name of the file") + .param("filename", STRING) + .returns(VOID) + .action("rebuild") + .tooltip("Recompiles only this file, returns a join point to the new recompiled file, or throws an exception if a problem happens") + .returns(jpRef("file")) + .action("insertBegin") + .tooltip("Adds the node in the join point to the start of the file") + .param("node", jpRef("joinpoint")) + .returns(VOID) + .action("insertBegin") + .tooltip("Adds the String as a Decl to the end of the file") + .param("code", STRING) + .returns(VOID) + .action("insertEnd") + .tooltip("Adds the node in the join point to the end of the file") + .param("node", jpRef("joinpoint")) + .returns(VOID) + .action("insertEnd") + .tooltip("Adds the String as a Decl to the end of the file") + .param("code", STRING) + .returns(VOID) + .action("addFunction") + .tooltip("Adds a function to the file that returns void and has no parameters") + .param("name", STRING) + .returns(jpRef("joinpoint")) + .action("setRelativeFolderpath") + .tooltip("Sets the path to the folder of the source file relative to the base source path") + .param("path", STRING) + .returns(VOID); + + // --- Declarations --- + + joinPoint("decl") + .tooltip("Represents one declaration (e.g., int foo(){return 0;}) or definition (e.g., int foo();)") + .attribute("attrs", array(jpRef("attribute")), "The attributes of this declaration (e.g. Pure, CUDAGlobal), if any"); + + joinPoint("namedDecl").extending("decl") + .tooltip("Represents a decl with a name") + .defaultAttribute("name") + .attribute("name", STRING) + .attribute("isPublic", BOOLEAN) + .attribute("qualifiedPrefix", STRING) + .attribute("qualifiedName", STRING) + .action("setName") + .tooltip("Sets the name of this namedDecl") + .param("name", STRING) + .returns(VOID) + .action("setQualifiedPrefix") + .tooltip("Sets the qualified prefix of this namedDecl") + .param("qualifiedPrefix", STRING) + .returns(VOID) + .action("setQualifiedName") + .tooltip("Sets the qualified name of this namedDecl (changes both the name and qualified prefix)") + .param("name", STRING) + .returns(VOID); + + joinPoint("declarator").extending("namedDecl") + .tooltip("Represents a decl that comes from a declarator (e.g., function, field, variable)"); + + joinPoint("include").extending("decl") + .tooltip("Represents an include directive (e.g., #include )") + .defaultAttribute("name") + .attribute("name", STRING) + .attribute("isAngled", BOOLEAN, "True if the include is angled (e.g., #include ) instead of quoted (e.g., #include \"myheader.h\")") + .attribute("relativeFolderpath", STRING, "The path to the folder of the source file of the include, relative to the name of the include"); + + joinPoint("record").extending("namedDecl") + .tooltip("Represents a record declaration (struct, union, or class)") + .attribute("kind", STRING) + .attribute("fields", array(jpRef("field"))) + .attribute("functions", array(jpRef("function"))) + .attribute("isImplementation", BOOLEAN, "True if this record declaration is an implementation (i.e., it has a body) instead of just a forward declaration") + .attribute("isPrototype", BOOLEAN, "True if this record declaration is a prototype (i.e., it has no body) instead of an implementation") + .action("addField") + .tooltip("Adds a field to a record (struct, class)") + .param("field", jpRef("field")) + .returns(VOID); + + joinPoint("field").extending("declarator") + .tooltip("Represents a member of a struct/union/class"); + + joinPoint("struct").extending("record") + .tooltip("Represents a struct declaration"); + + joinPoint("class").extending("record") + .tooltip("Represents a C++ class declaration") + .defaultAttribute("name") + .attribute("methods", array(jpRef("method")), "The methods of this class") + .attribute("bases", array(jpRef("class")), "The base classes of this class") + .attribute("allMethods", array(jpRef("method")), "The methods of this class and its base classes") + .attribute("allBases", array(jpRef("class")), "The base classes of this class and its base classes") + .attribute("isAbstract", BOOLEAN, "True if this class contains at least one pure function") + .attribute("isInterface", BOOLEAN, "True if this class contains only pure functions") + .attribute("prototypes", array(jpRef("class")), "The prototypes (or declarations) of this class present in the AST, if any") + .attribute("implementation", jpRef("class"), "The implementation (or definition) of this class present in the AST, or undefined if none is found") + .attribute("canonical", jpRef("class"), "Class join points can either represent declarations or definitions, returns the definition of this class, if present, or the first declaration, if only declarations are present") + .attribute("isCanonical", BOOLEAN, "True if this class join point is the canonical one, which is the definition if it is present, or the first declaration if only declarations are present") + .action("addMethod") + .tooltip("Adds a method to a class. If the given method has a definition, creates an equivalent declaration and adds it to the class, otherwise simply adds the declaration to the class. In both cases, the declaration is only added to the class if there is no declaration already with the same signature") + .param("method", jpRef("method")) + .returns(VOID); + + joinPoint("vardecl").extending("declarator") + .tooltip("Represents a variable declaration or definition") + .defaultAttribute("name") + .attribute("hasInit", BOOLEAN, "True if this variable declaration has an initializer") + .attribute("init", jpRef("expression"), "The initializer of this variable declaration, if it has one") + .attribute("initStyle", STRING, "The initialization style of this vardecl, which can be no_init, cinit, callinit, listinit") + .attribute("isParam", BOOLEAN, "True if this variable declaration is a function parameter") + .attribute("storageClass", enumRef("StorageClass"), "The storage class of this variable declaration. Can be 'none', 'extern', 'static', '__private_extern__', 'auto' or 'register'") + .attribute("isGlobal", BOOLEAN, "True if this variable declaration is global. This includes all global variables as well as static variables declared within a function.") + .attribute("definition", jpRef("vardecl"), "The vardecl corresponding to the actual definition. For global variables, returns the vardecl of the file where it is actually defined (instead of the vardecl that defines an external link to the variable)") + .action("setInit") + .tooltip("Sets the given expression as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization") + .param("init", jpRef("expression")) + .returns(VOID) + .action("setInit") + .tooltip("Converts the given string to a literal expression and sets it as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization") + .param("init", STRING) + .returns(VOID) + .action("removeInit") + .tooltip("If vardecl already has an initialization, removes it") + .param("removeConst", BOOLEAN, "true") + .returns(VOID) + .action("varref") + .tooltip("Creates a new varref based on this vardecl") + .returns(jpRef("varref")) + .action("setStorageClass") + .tooltip("Sets the storage class specifier, which can be none, extern, static, __private_extern__, auto") + .param("storageClass", enumRef("StorageClass")) + .returns(VOID); + + joinPoint("typedefNameDecl").extending("namedDecl") + .tooltip("Base node for declarations which introduce a typedef-name"); + + joinPoint("typedefDecl").extending("typedefNameDecl") + .tooltip("Declaration of a typedef-name via the 'typedef' type specifier"); + + joinPoint("enumDecl").extending("namedDecl") + .tooltip("Represents an enum declaration") + .attribute("enumerators", array(jpRef("enumeratorDecl"))); + + joinPoint("enumeratorDecl").extending("namedDecl") + .tooltip("Represents an enumerator in an enum"); + + joinPoint("labelDecl").extending("namedDecl") + .tooltip("Represents a label declaration") + .attribute("labelStmt", jpRef("labelStmt")); + + joinPoint("accessSpecifier").extending("decl") + .tooltip("Represents an access specifier (public:, private:, or protected:) in a class declaration") + .defaultAttribute("kind") + .attribute("kind", STRING, "The type of specifier. Can return 'public', 'protected', 'private' or 'none'"); + + joinPoint("param").extending("vardecl") + .tooltip("Represents a function parameter"); + + joinPoint("function").extending("declarator") + .tooltip("Represents a function declaration or definition") + .attribute("hasDefinition", BOOLEAN, "[DEPRECATED: Use .isImplementation instead] True if this particular function join point has a body, false otherwise") + .attribute("isImplementation", BOOLEAN, "True if this function join point is an implementation, false otherwise") + .attribute("isPrototype", BOOLEAN, "True if this function join point is a prototype, false otherwise") + .attribute("functionType", jpRef("functionType"), "The function type of this function, which includes the return type and the parameter types") + .attribute("declarationJp", jpRef("function"), "Returns the first prototype of this function that could be found, or undefined if there is none") + .attribute("declarationJps", array(jpRef("function")), "Returns the prototypes of this function that are present in the code. If there are none, returns an empty array") + .attribute("definitionJp", jpRef("function"), "Returns the implementation of this function if there is one, or undefined otherwise") + .attribute("getDeclaration") + .param("withReturnType", BOOLEAN) + .returns(STRING) + .attribute("body", jpRef("scope")) + .attribute("paramNames", array(STRING)) + .attribute("params", array(jpRef("param"))) + .attribute("id", STRING) + .attribute("isInline", BOOLEAN) + .attribute("isVirtual", BOOLEAN) + .attribute("isModulePrivate", BOOLEAN) + .attribute("isPure", BOOLEAN) + .attribute("isDelete", BOOLEAN) + .attribute("storageClass", enumRef("StorageClass")) + .attribute("calls", array(jpRef("call"))) + .attribute("signature", STRING, "The signature of this function (e.g., name of the function, plus the parameters types)") + .attribute("returnType", jpRef("type")) + .attribute("isCudaKernel", BOOLEAN) + .attribute("canonical", jpRef("function"), "Function join points can either represent declarations or definitions, returns the definition of this function, if present, or the first declaration, if only declarations are present") + .attribute("isCanonical", BOOLEAN, "True, if this is the function returned by the 'canonical' attribute") + .action("clone") + .tooltip("Clones this function assigning it a new name, inserts the cloned function after the original function. If the name is the same and the original method, automatically removes the cloned method from the class") + .param("newName", STRING) + .param("insert", BOOLEAN, "true") + .returns(jpRef("function")) + .action("cloneOnFile") + .tooltip("Generates a clone of the provided function on a new file with the provided name (or with a weaver-generated name if one is not provided)") + .param("newName", STRING) + .param("fileName", STRING, "null") + .returns(jpRef("function")) + .action("cloneOnFile") + .tooltip("Generates a clone of the provided function on a new file (with the provided join point)") + .param("newName", STRING) + .param("file", jpRef("file")) + .returns(jpRef("function")) + .action("insertReturn") + .tooltip("Inserts the joinpoint before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node") + .param("code", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("insertReturn") + .tooltip("Inserts code as a literal statement before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node") + .param("code", STRING) + .returns(jpRef("joinpoint")) + .action("setParams") + .tooltip("Sets the parameters of the function") + .param("params", array(jpRef("param"))) + .returns(VOID) + .action("setParamsFromStrings") + .tooltip("Overload that accepts strings that represent type-varname pairs (e.g., int param1)") + .param("params", array(STRING)) + .returns(VOID) + .action("setParam") + .tooltip("Sets the parameter of the function at the given position") + .param("index", INT) + .param("param", jpRef("param")) + .returns(VOID) + .action("setParam") + .tooltip("Sets the parameter of the function at the given position") + .param("index", INT) + .param("name", STRING) + .param("type", jpRef("type"), "null") + .returns(VOID) + .action("setBody") + .tooltip("Sets the body of the function") + .param("body", jpRef("scope")) + .returns(VOID) + .action("newCall") + .tooltip("Creates a new call to this function") + .param("args", array(jpRef("joinpoint"))) + .returns(jpRef("call")) + .action("setFunctionType") + .tooltip("Sets the type of the function") + .param("functionType", jpRef("functionType")) + .returns(VOID) + .action("setReturnType") + .tooltip("Sets the return type of the function") + .param("returnType", jpRef("type")) + .returns(VOID) + .action("setParamType") + .tooltip("Sets the type of a parameter of the function") + .param("index", INT) + .param("newType", jpRef("type")) + .returns(VOID) + .action("addParam") + .tooltip("Adds a new parameter to the function") + .param("param", jpRef("param")) + .returns(VOID) + .action("addParam") + .tooltip("Adds a new parameter to the function") + .param("name", STRING) + .param("type", jpRef("type"), "null") + .returns(VOID) + .action("setStorageClass") + .tooltip("Sets the storage class of this specific function decl. AUTO and REGISTER are not allowed for functions, and EXTERN is not allowed in function implementations, or function declarations that are in the same file as the implementation. Returns true if the storage class changed, false otherwise") + .param("storageClass", enumRef("StorageClass")) + .returns(BOOLEAN); + + joinPoint("method").extending("function") + .tooltip("Represents a method in a class declaration") + .defaultAttribute("name") + .attribute("record", jpRef("class")) + .action("removeRecord") + .tooltip("Removes the class of the method") + .returns(VOID); + + // --- Pragmas --- + + joinPoint("pragma") + .tooltip("Represents a pragma in the code (e.g., #pragma kernel)") + .defaultAttribute("name") + .attribute("name", STRING, "The name of the pragma. E.g. for #pragma foo bar, returns 'foo'") + .attribute("target", jpRef("joinpoint"), "The first node below the pragma that is not a comment or another pragma. Example of pragma targets are statements and declarations") + .attribute("content", STRING, "Everything that is after the name of the pragma") + .attribute("getTargetNodes") + .tooltip("All the nodes below the target node, including the target node, up until a pragma with the name given by argument 'endPragma'. If no end pragma is found, returns the same result as if not providing the argument") + .param("endPragma", STRING, "null") + .returns(array(jpRef("joinpoint"))) + .action("setName") + .param("name", STRING) + .returns(VOID) + .action("setContent") + .param("content", STRING) + .returns(VOID); + + joinPoint("marker").extending("pragma") + .tooltip( + "Represents a marker pragma, which is used to mark a specific node in the code (e.g., #pragma myMarker) and can be used to store custom data") + .defaultAttribute("id") + .attribute("id", STRING) + .attribute("contents", jpRef("scope"), "The scope that is targeted by the marker"); + + joinPoint("tag").extending("pragma") + .tooltip("Represents a tag pragma, which is used to reference a specific node in the code") + .defaultAttribute("id") + .attribute("id", STRING); + + joinPoint("omp").extending("pragma") + .tooltip("Represents an OpenMP pragma (e.g., #pragma omp parallel)") + .defaultAttribute("kind") + .attribute("kind", STRING, "The kind of the directive") + .attribute("numThreads", STRING, "An integer expression, or undefined if no 'num_threads' clause is defined") + .attribute("procBind", STRING, "One of 'master', 'close' or 'spread', or undefined if no 'proc_bind' clause is defined") + .attribute("private", array(STRING), "The variable names of all private clauses, or empty array if no private clause is defined") + .attribute("hasClause") + .tooltip("True if the directive has at least one clause of the given clause kind, false otherwise") + .param("clauseName", STRING) + .returns(BOOLEAN) + .attribute("isClauseLegal") + .tooltip("True if the directive has the given clause kind, false otherwise") + .param("clauseName", STRING) + .returns(BOOLEAN) + .attribute("clauseKinds", array(STRING), "The names of the kinds of all clauses in the pragma, or empty array if no clause is defined") + .attribute("getReduction") + .tooltip("The variable names for the given reduction kind, or empty array if no reduction of that kind is defined") + .param("kind", STRING) + .returns(array(STRING)) + .attribute("reductionKinds", array(STRING), "The reduction kinds in the reductions clauses of the this pragma, or empty array if no reduction is defined") + .attribute("default", STRING, "One of 'shared' or 'none', or undefined if no 'default' clause is defined") + .attribute("firstprivate", array(STRING), "The variable names of all firstprivate clauses, or empty array if no firstprivate clause is defined") + .attribute("lastprivate", array(STRING), "The variable names of all lastprivate clauses, or empty array if no lastprivate clause is defined") + .attribute("shared", array(STRING), "The variable names of all shared clauses, or empty array if no shared clause is defined") + .attribute("copyin", array(STRING), "The variable names of all copyin clauses, or empty array if no copyin clause is defined") + .attribute("scheduleKind", STRING, "One of 'static', 'dynamic', 'guided', 'auto' or 'runtime', or undefined if no 'schedule' clause is defined") + .attribute("scheduleChunkSize", STRING, "An integer expression, or undefined if no 'schedule' clause with chunk size is defined") + .attribute("scheduleModifiers", array(STRING), "A list with possible values of 'monotonic', 'nonmonotonic' or 'simd', or undefined if no 'schedule' clause with modifiers is defined") + .attribute("collapse", STRING, "An integer expression, or undefined if no 'collapse' clause is defined") + .attribute("ordered", STRING, "An integer expression, or undefined if no 'ordered' clause with a parameter is defined") + .action("setKind") + .tooltip("Sets the directive kind of the OpenMP pragma. Any unsupported clauses will be discarded") + .param("directiveKind", STRING) + .returns(VOID) + .action("removeClause") + .tooltip("Removes any clause of the given kind from the OpenMP pragma") + .param("clauseKind", STRING) + .returns(VOID) + .action("setNumThreads") + .tooltip("Sets the value of the num_threads clause of an OpenMP pragma") + .param("newExpr", STRING) + .returns(VOID) + .action("setProcBind") + .tooltip("Sets the value of the proc_bind clause of an OpenMP pragma") + .param("newBind", STRING) + .returns(VOID) + .action("setPrivate") + .tooltip("Sets the variables of a private clause of an OpenMP pragma") + .param("newVariables", array(STRING)) + .returns(VOID) + .action("setReduction") + .tooltip("Sets the variables for a given kind of a reduction clause of an OpenMP pragma") + .param("kind", STRING) + .param("newVariables", array(STRING)) + .returns(VOID) + .action("setDefault") + .tooltip("Sets the value of the default clause of an OpenMP pragma") + .param("newDefault", STRING) + .returns(VOID) + .action("setFirstprivate") + .tooltip("Sets the variables of a firstprivate clause of an OpenMP pragma") + .param("newVariables", array(STRING)) + .returns(VOID) + .action("setLastprivate") + .tooltip("Sets the variables of a lastprivate clause of an OpenMP pragma") + .param("newVariables", array(STRING)) + .returns(VOID) + .action("setShared") + .tooltip("Sets the variables of a shared clause of an OpenMP pragma") + .param("newVariables", array(STRING)) + .returns(VOID) + .action("setCopyin") + .tooltip("Sets the variables of a copyin clause of an OpenMP pragma") + .param("newVariables", array(STRING)) + .returns(VOID) + .action("setScheduleKind") + .tooltip("Sets the value of the schedule clause of an OpenMP pragma") + .param("scheduleKind", STRING) + .returns(VOID) + .action("setScheduleChunkSize") + .tooltip("Sets the value of the chunk size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception") + .param("chunkSize", STRING) + .returns(VOID) + .action("setScheduleChunkSize") + .tooltip("Sets the value of the chunk size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception") + .param("chunkSize", INT) + .returns(VOID) + .action("setScheduleModifiers") + .tooltip("Sets the value of the modifiers in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception") + .param("modifiers", array(STRING)) + .returns(VOID) + .action("setCollapse") + .tooltip("Sets the value of the collapse clause of an OpenMP pragma") + .param("newExpr", STRING) + .returns(VOID) + .action("setCollapse") + .tooltip("Sets the value of the collapse clause of an OpenMP pragma") + .param("newExpr", INT) + .returns(VOID) + .action("setOrdered") + .tooltip("Sets the value of the ordered clause of an OpenMP pragma") + .param("parameters", STRING, "null") + .returns(VOID); + + // --- Statements --- + + joinPoint("statement") + .attribute("isFirst", BOOLEAN) + .attribute("isLast", BOOLEAN); + + joinPoint("scope").extending("statement") + .tooltip("Represents a group of statements (e.g., function body, loop body, if/else body, etc.)") + .attribute("getNumStatements") + .tooltip("The number of statements in the scope, including the statements inside the declaration and bodies of structures such as ifs and loops, and not considering comments and pragmas. If flat is true, does not consider the statements inside structures such as ifs and loops (e.g., a loop counts as one statement)") + .param("flat", BOOLEAN, "false") + .returns(LONG) + .attribute("naked", BOOLEAN, "True if the scope does not have curly braces") + .attribute("stmts", array(jpRef("statement")), "Returns the direct (children) statements of this scope") + .attribute("allStmts", array(jpRef("statement")), "Returns the descendant statements of this scope, excluding other scopes, loops, ifs and wrapper statements") + .attribute("firstStmt", jpRef("statement"), "Returns the first statement in the scope") + .attribute("lastStmt", jpRef("statement"), "Returns the last statement in the scope") + .attribute("owner", jpRef("joinpoint"), "The statement that owns the scope (e.g., function, loop...)") + .action("insertBegin") + .param("node", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("insertBegin") + .param("code", STRING) + .returns(jpRef("joinpoint")) + .action("insertEnd") + .param("node", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("insertEnd") + .param("code", STRING) + .returns(jpRef("joinpoint")) + .action("insertReturn") + .tooltip("Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node") + .param("code", jpRef("joinpoint")) + .returns(jpRef("joinpoint")) + .action("insertReturn") + .tooltip("Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node") + .param("code", STRING) + .returns(jpRef("joinpoint")) + .action("addLocal") + .tooltip("Adds a new local variable to this scope") + .param("name", STRING) + .param("type", jpRef("joinpoint")) + .param("initValue", STRING, "null") + .returns(jpRef("joinpoint")) + .action("setNaked") + .tooltip("Sets the 'naked' status of a scope (a scope is naked if it does not have curly braces)") + .param("isNaked", BOOLEAN) + .returns(VOID) + .action("clear") + .tooltip("Clears the contents of this scope (untested)") + .returns(VOID) + .action("cfg") + .tooltip("CFG tester") + .returns(STRING) + .action("dfg") + .tooltip("DFG tester") + .returns(STRING); + + joinPoint("body").extending("scope"); + + joinPoint("loop").extending("statement") + .defaultAttribute("kind") + .attribute("kind", enumRef("LoopKind")) + .attribute("id", STRING, "Uniquely identifies the loop inside the program") + .attribute("isInnermost", BOOLEAN) + .attribute("isOutermost", BOOLEAN) + .attribute("nestedLevel", INT) + .attribute("controlVar", STRING) + .attribute("controlVarref", jpRef("varref")) + .attribute("rank", array(INT)) + .attribute("isParallel", BOOLEAN) + .attribute("iterations", INTEGER) + .attribute("iterationsExpr", jpRef("expression")) + .attribute("isInterchangeable") + .tooltip("True if this loop can be interchanged with the given loop, which means that they are adjacent and have no data dependencies that would prevent their interchange. This is a conservative test.") + .param("otherLoop", jpRef("loop")) + .returns(BOOLEAN) + .attribute("init", jpRef("statement"), "The statement of the loop initialization") + .attribute("initValue", STRING, "The expression of the first value of the control variable (e.g. '0' in 'size_t i = 0;')") + .attribute("cond", jpRef("statement"), "The statement of the loop condition") + .attribute("step", jpRef("statement"), "The statement of the loop step") + .attribute("endValue", STRING, "The expression of the last value of the control variable (e.g. '10' in 'size_t i = 0; i < 10; i++')") + .attribute("stepValue", STRING, "The expression of the step value of the control variable (e.g. '1' in 'size_t i = 0; i < 10; i++')") + .attribute("hasCondRelation", BOOLEAN, "True if the condition of the loop in the canonical format, and is one of: <, <=, >, >=") + .attribute("condRelation", enumRef("Relation")) + .attribute("body", jpRef("scope")) + .action("setKind") + .tooltip("Sets the kind of the loop") + .param("kind", enumRef("LoopKind")) + .returns(VOID) + .action("setInit") + .tooltip("Sets the init statement of the loop") + .param("initCode", STRING) + .returns(VOID) + .action("setInitValue") + .tooltip("Sets the init value of the loop. Works with loops of kind 'for'") + .param("initCode", STRING) + .returns(VOID) + .action("setEndValue") + .tooltip("Sets the end value of the loop. Works with loops of kind 'for'") + .param("initCode", STRING) + .returns(VOID) + .action("setCond") + .tooltip("Sets the conditional statement of the loop. Works with loops of kind 'for'") + .param("condCode", STRING) + .returns(VOID) + .action("setStep") + .tooltip("Sets the step statement of the loop. Works with loops of kind 'for'") + .param("stepCode", STRING) + .returns(VOID) + .action("setIsParallel") + .tooltip("Sets the attribute 'isParallel' of the loop") + .param("isParallel", BOOLEAN) + .returns(VOID) + .action("interchange") + .tooltip("Interchanges two for loops, if possible") + .param("otherLoop", jpRef("loop")) + .returns(VOID) + .action("tile") + .tooltip("Applies loop tiling to this loop") + .param("blockSize", STRING) + .param("reference", jpRef("statement")) + .param("useTernary", BOOLEAN, "true") + .returns(jpRef("statement")) + .action("setCondRelation") + .tooltip("Changes the operator of a canonical condition, if possible. Supported operators: lt, le, gt, ge") + .param("operator", enumRef("Relation")) + .returns(VOID) + .action("setBody") + .tooltip("Sets the body of the loop") + .param("body", jpRef("scope")) + .returns(VOID); + + joinPoint("if").extending("statement") + .attribute("cond", jpRef("expression")) + .attribute("condDecl", jpRef("vardecl")) + .attribute("then", jpRef("scope")) + .attribute("else", jpRef("scope")) + .action("setCond") + .tooltip("Sets the condition of the if") + .param("cond", jpRef("expression")) + .returns(VOID) + .action("setThen") + .tooltip("Sets the body of the if") + .param("then", jpRef("statement")) + .returns(VOID) + .action("setElse") + .tooltip("Sets the body of the else") + .param("else", jpRef("statement")) + .returns(VOID); + + joinPoint("wrapperStmt").extending("statement") + .attribute("kind", enumRef("WrapperStatementKind")) + .attribute("content", jpRef("joinpoint")); + + joinPoint("returnStmt").extending("statement") + .attribute("returnExpr", jpRef("expression")); + + joinPoint("switch").extending("statement") + .attribute("hasDefaultCase", BOOLEAN, "True if there is a default case in this switch statement, false otherwise") + .attribute("getDefaultCase", jpRef("case"), "The default case statement of this switch statement or undefined if it does not have a default case") + .attribute("cases", array(jpRef("case")), "The case statements inside this switch") + .attribute("condition", jpRef("expression")); + + joinPoint("switchCase").extending("statement"); + + joinPoint("case").extending("switchCase") + .attribute("isDefault", BOOLEAN) + .attribute("isEmpty", BOOLEAN, "True if this case does not contain instructions (i.e., it is directly above another case), false otherwise") + .attribute("nextInstruction", jpRef("statement"), "The first statement that is not a case that will be executed by this case statement") + .attribute("instructions", array(jpRef("statement")), "The instructions that are associated with this case in the source code. This does not represent what instructions are actually executed (e.g., if a case does not have a break, does not show instructions of the next case)") + .attribute("nextCase", jpRef("case"), "The case statement that comes after this case, or undefined if there are no more case statements") + .attribute("values", array(jpRef("expression")), "The values that the case statement will match. It can return zero (e.g., 'default:'), one (e.g., 'case 1:') or two (e.g., 'case 2...4:') expressions, depending on the format of the case"); + + joinPoint("default").extending("switchCase"); + + joinPoint("declStmt").extending("statement") + .attribute("decls", array(jpRef("decl")), "The declarations in this statement"); + + joinPoint("exprStmt").extending("statement") + .attribute("expr", jpRef("expression"), "The expression join point associated to this exprStmt"); + + joinPoint("gotoStmt").extending("statement") + .attribute("label", jpRef("labelDecl")) + .action("setLabel") + .tooltip("Sets the label of the goto") + .param("label", jpRef("labelDecl")) + .returns(VOID); + + joinPoint("labelStmt").extending("statement") + .attribute("decl", jpRef("labelDecl")) + .action("setDecl") + .tooltip("Sets the label of the label statement") + .param("label", jpRef("labelDecl")) + .returns(VOID); + + joinPoint("emptyStmt").extending("statement"); + + joinPoint("continue").extending("statement"); + + joinPoint("break").extending("statement") + .attribute("enclosingStmt", jpRef("statement"), "The enclosing statement related to this break. It should be either a loop or a switch statement."); + + joinPoint("asmStmt").extending("statement") + .attribute("isSimple", BOOLEAN) + .attribute("isVolatile", BOOLEAN) + .attribute("clobbers", array(STRING)); + + // --- Expressions --- + + joinPoint("expression") + .attribute("decl", jpRef("decl"), "A 'decl' join point that represents the declaration associated with this expression, or undefined if there is none") + .attribute("vardecl", jpRef("vardecl"), "A 'vardecl' join point that represents the variable declaration associated with this expression, or undefined if there is none") + .attribute("use", enumRef("ExpressionUse")) + .attribute("isFunctionArgument", BOOLEAN, "True if the expression is part of an argument of a function call") + .attribute("implicitCast", jpRef("cast"), "Returns a cast joinpoint if this expression has an associated implicit cast, undefined otherwise"); + + joinPoint("call").extending("expression") + .defaultAttribute("name") + .attribute("name", STRING) + .attribute("numArgs", INT) + .attribute("memberNames", array(STRING)) + .attribute("declaration", jpRef("function"), "A 'function' join point that represents the function of the call that was found, it can return either an implementation or a function prototype; 'undefined' if no declaration was found") + .attribute("definition", jpRef("function"), "A 'function' join point that represents the function definition of the call; 'undefined' if no definition was found") + .attribute("argList", array(jpRef("expression")), "[DEPRECATED:] An alias for 'args'") + .attribute("args", array(jpRef("expression")), "An array with the arguments of the call") + .attribute("getArg") + .param("index", INT) + .returns(jpRef("expression")) + .attribute("returnType", jpRef("type"), "The return type of the call") + .attribute("functionType", jpRef("functionType"), "The function type of the call, which includes the return type and the types of the parameters") + .attribute("isMemberAccess", BOOLEAN) + .attribute("memberAccess", jpRef("memberAccess")) + .attribute("isStmtCall", BOOLEAN) + .attribute("function", jpRef("function"), "A function join point associated with this call. If a definition is present, it is given priority over returning a declaration. If only declarations are present, returns a declaration") + .attribute("signature", STRING, "Similar to $function.signature, but if no function decl could be found (e.g., function from system include), returns a signature based on just the name of the function") + .attribute("directCallee", jpRef("function"), "A function join point that represents the 'raw' function of the call (e.g. if this is a call to a templated function, returns a declaration representing the template specialization, instead of the original function)") + .action("setName") + .tooltip("Changes the name of the call") + .param("name", STRING) + .returns(VOID) + .action("wrap") + .tooltip("Wraps this call with a possibly new wrapping function") + .param("name", STRING) + .returns(VOID) + .action("inline") + .tooltip("Tries to inline this call") + .returns(BOOLEAN) + .action("setArgFromString") + .param("index", INT) + .param("expr", STRING) + .returns(VOID) + .action("setArg") + .param("index", INT) + .param("expr", jpRef("expression")) + .returns(VOID) + .action("addArg") + .tooltip("Adds an argument at the end of the call, creating an expression using the given code and type. If a type is not provided, a dummy type is used") + .param("argCode", STRING) + .param("type", jpRef("type"), "null") + .returns(VOID) + .action("addArg") + .tooltip("Adds an argument at the end of the call, creating a literal 'type' from the type string") + .param("arg", STRING) + .param("type", STRING) + .returns(VOID); + + joinPoint("memberCall").extending("call") + .attribute("base", jpRef("expression")) + .attribute("rootBase", jpRef("expression")); + + joinPoint("cudaKernelCall").extending("call") + .attribute("config", array(jpRef("expression"))) + .action("setConfig") + .param("args", array(jpRef("expression"))) + .returns(VOID) + .action("setConfigFromStrings") + .param("args", array(STRING)) + .returns(VOID); + + joinPoint("op").extending("expression") + .attribute("operator", STRING) + .attribute("kind", enumRef("OpKind"), "The kind of the operator. If it is a binary operator, can be one of: ptr_mem_d, ptr_mem_i, mul, div, rem, add, sub, shl, shr, cmp, lt, gt, le, ge, eq, ne, and, xor, or, l_and, l_or, assign, mul_assign, div_assign, rem_assign, add_assign, sub_assign, shl_assign, shr_assign, and_assign, xor_assign, or_assign, comma. If it is a unary operator, can be one of: post_inc, post_dec, pre_inc, pre_dec, addr_of, deref, plus, minus, not, l_not, real, imag, extension, cowait. If it is a ternary operator, the value will be 'ternary'") + .attribute("isBitwise", BOOLEAN); + + joinPoint("binaryOp").extending("op") + .attribute("left", jpRef("expression")) + .attribute("right", jpRef("expression")) + .attribute("isAssignment", BOOLEAN) + .action("setLeft") + .param("left", jpRef("expression")) + .returns(VOID) + .action("setRight") + .param("right", jpRef("expression")) + .returns(VOID); + + joinPoint("unaryOp").extending("op") + .attribute("operand", jpRef("expression")) + .attribute("isPointerDeref", BOOLEAN); + + joinPoint("ternaryOp").extending("op") + .attribute("cond", jpRef("expression")) + .attribute("trueExpr", jpRef("expression")) + .attribute("falseExpr", jpRef("expression")); + + joinPoint("newExpr").extending("expression"); + + joinPoint("deleteExpr").extending("expression"); + + joinPoint("varref").extending("expression") + .tooltip("A reference to a variable") + .defaultAttribute("name") + .attribute("name", STRING) + .attribute("kind", STRING) + .attribute("useExpr", jpRef("expression"), "Expression from where the attribute 'use' is calculated. In certain cases (e.g., array access, pointer dereference) the 'use' attribute is not calculated on the node itself, but on an ancestor of the node. This attribute returns that node") + .attribute("isFunctionCall", BOOLEAN, "True if this varref represents a function call") + .attribute("declaration", jpRef("declarator")) + .attribute("property", STRING, "If this variable reference has a MS-style property, returns the property name. Returns undefined otherwise") + .attribute("hasProperty", BOOLEAN, "True if this variable reference has a MS-style property, false otherwise") + .action("setName") + .param("name", STRING) + .returns(VOID); + + joinPoint("cast").extending("expression") + .attribute("isImplicitCast", BOOLEAN, "[DEPRECATED: Use expr.implicitCast instead]") + .attribute("fromType", jpRef("type")) + .attribute("toType", jpRef("type")) + .attribute("subExpr", jpRef("expression")); + + joinPoint("parenExpr").extending("expression") + .attribute("subExpr", jpRef("expression"), "Returns the expression inside this parenthesis expression"); + + joinPoint("arrayAccess").extending("expression") + .attribute("arrayVar", jpRef("expression"), "Expression representing the variable of the array access (can be a varref, memberAccess...)") + .attribute("subscript", array(jpRef("expression")), "Expression of the array access subscript") + .attribute("parentAccess", jpRef("arrayAccess"), "A view of the current arrayAccess without the last subscript, or undefined if this arrayAccess only has one subscript") + .attribute("numSubscripts", INT, "The number of subscripts of this array access") + .attribute("name", STRING, "If the array access is done over a variable, returns the name of the variable. Equivalent to $arrayAccess.arrayVar.name"); + + joinPoint("memberAccess").extending("expression") + .attribute("name", STRING) + .attribute("memberChain", array(jpRef("expression"))) + .attribute("memberChainNames", array(STRING)) + .attribute("base", jpRef("expression"), "Expression of the base of this member access") + .attribute("arrow", BOOLEAN, "True if this is a member access that uses arrow (i.e., foo->bar), false if uses dot (i.e., foo.bar)") + .action("setArrow") + .param("isArrow", BOOLEAN) + .returns(VOID); + + joinPoint("unaryExprOrType").extending("expression") + .attribute("kind", STRING) + .attribute("hasTypeExpr", BOOLEAN) + .attribute("hasArgExpr", BOOLEAN) + .attribute("argType", jpRef("type")) + .attribute("argExpr", jpRef("expression")) + .action("setArgType") + .param("argType", jpRef("type")) + .returns(VOID); + + joinPoint("This").extending("expression"); + + joinPoint("literal").extending("expression"); + + joinPoint("intLiteral").extending("literal") + .attribute("value", LONG); + + joinPoint("floatLiteral").extending("literal") + .attribute("value", DOUBLE); + + joinPoint("boolLiteral").extending("literal") + .attribute("value", BOOLEAN); + + joinPoint("initList").extending("expression") + .attribute("arrayFiller", jpRef("expression"), "[May be undefined] If this initializer list initializes an array with more elements than there are initializers in the list, specifies an expression to be used for value initialization of the rest of the elements"); + + joinPoint("implicitValue").extending("expression"); + + // --- Comment --- + + joinPoint("comment") + .attribute("text", STRING) + .action("setText") + .param("text", STRING) + .returns(VOID); + + // --- Cilk --- + + joinPoint("cilkFor").extending("loop"); + + joinPoint("cilkSync").extending("statement"); + + joinPoint("cilkSpawn").extending("call"); + + // --- Attribute --- + + joinPoint("attribute") + .attribute("kind", STRING); + + // --- Types --- + + joinPoint("type") + .attribute("kind", STRING) + .attribute("isTopLevel", BOOLEAN) + .attribute("isArray", BOOLEAN) + .attribute("isPointer", BOOLEAN) + .attribute("isAuto", BOOLEAN, "True if this is a type declared with the 'auto' keyword") + .attribute("arraySize", INT) + .attribute("arrayDims", array(INT)) + .attribute("hasTemplateArgs", BOOLEAN) + .attribute("templateArgsStrings", array(STRING)) + .attribute("templateArgsTypes", array(jpRef("type"))) + .attribute("hasSugar", BOOLEAN) + .attribute("desugar", jpRef("type"), "Single-step desugar. Returns the type itself if it does not have sugar") + .attribute("desugarAll", jpRef("type"), "Completely desugars the type") + .attribute("isBuiltin", BOOLEAN) + .attribute("constant", BOOLEAN) + .attribute("unwrap", jpRef("type"), "If the type encapsulates another type, returns the encapsulated type") + .attribute("normalize", jpRef("type"), "Ignores certain types (e.g., DecayedType)") + .attribute("typeFields", map(STRING, jpRef("type")), "Maps names of join point fields that represent type join points, to their respective values") + .attribute("fieldTree", STRING, "A tree representation of the fields of this type") + .action("setTemplateArgsTypes") + .tooltip("Sets the template argument types of a template type") + .param("templateArgTypes", array(jpRef("type"))) + .returns(VOID) + .action("setTemplateArgType") + .tooltip("Sets a single template argument type of a template type") + .param("index", INT) + .param("templateArgType", jpRef("type")) + .returns(VOID) + .action("setDesugar") + .tooltip("Sets the desugared type of this type") + .param("desugaredType", jpRef("type")) + .returns(VOID) + .action("setTypeFieldByValueRecursive") + .tooltip("Changes a single occurrence of a type field that has the current value with new value. Returns true if there was a change") + .param("currentValue", OBJECT) + .param("newValue", OBJECT) + .returns(BOOLEAN) + .action("setUnderlyingType") + .tooltip("Replaces an underlying type of this instance with new type, if it matches the old type") + .param("oldValue", jpRef("type")) + .param("newValue", jpRef("type")) + .returns(jpRef("type")) + .action("asConst") + .tooltip("Returns a new node based on this type with the qualifier const") + .returns(jpRef("type")); + + joinPoint("pointerType").extending("type") + .attribute("pointee", jpRef("type")) + .attribute("pointerLevels", INT, "Number of pointer levels from this pointer") + .action("setPointee") + .tooltip("Sets the pointee type of this pointer type") + .param("pointeeType", jpRef("type")) + .returns(VOID); + + joinPoint("arrayType").extending("type") + .attribute("elementType", jpRef("type")) + .action("setElementType") + .tooltip("Sets the element type of the array") + .param("arrayElementType", jpRef("type")) + .returns(VOID); + + joinPoint("adjustedType").extending("type") + .attribute("originalType", jpRef("type"), "The type that is being adjusted"); + + joinPoint("variableArrayType").extending("arrayType") + .attribute("sizeExpr", jpRef("expression")) + .action("setSizeExpr") + .tooltip("Sets the size expression of this variable array type") + .param("sizeExpr", jpRef("expression")) + .returns(VOID); + + joinPoint("incompleteArrayType").extending("arrayType"); + + joinPoint("tagType").extending("type") + .attribute("name", STRING) + .attribute("decl", jpRef("decl"), "A 'decl' join point that represents the declaration of this tag type"); + + joinPoint("enumType").extending("tagType") + .attribute("integerType", jpRef("type")); + + joinPoint("templateSpecializationType").extending("type") + .attribute("templateName", STRING) + .attribute("numArgs", INT) + .attribute("args", array(STRING)) + .attribute("firstArgType", jpRef("type")); + + joinPoint("functionType").extending("type") + .attribute("returnType", jpRef("type")) + .attribute("paramTypes", array(jpRef("type"))) + .action("setReturnType") + .tooltip("Sets the return type of the FunctionType") + .param("newType", jpRef("type")) + .returns(VOID) + .action("setParamType") + .tooltip("Sets the type of a parameter of the FunctionType. Be careful that if you directly change the type of a parameter and the function type is associated with a function declaration, this change will not be reflected in the function. If you want to change the type of a parameter of a function declaration, use function.setParamType") + .param("index", INT) + .param("newType", jpRef("type")) + .returns(VOID); + + joinPoint("qualType").extending("type") + .attribute("qualifiers", array(STRING)) + .attribute("unqualifiedType", jpRef("type")); + + joinPoint("builtinType").extending("type") + .attribute("builtinKind", STRING) + .attribute("isInteger", BOOLEAN, "True, if it is an integer type") + .attribute("isFloat", BOOLEAN, "True, if it is a floating type (e.g., float, double)") + .attribute("isSigned", BOOLEAN, "True, if it is a signed type") + .attribute("isUnsigned", BOOLEAN, "True, if it is an unsigned type") + .attribute("isVoid", BOOLEAN, "True, if it is a void type"); + + joinPoint("parenType").extending("type") + .attribute("innerType", jpRef("type")) + .action("setInnerType") + .tooltip("Sets the inner type of this paren type") + .param("innerType", jpRef("type")) + .returns(VOID); + + joinPoint("undefinedType").extending("type"); + + joinPoint("elaboratedType").extending("type") + .tooltip( + "Represents a type that was referred to using an elaborated type keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, or both. This type is used to keep track of a type name as written in the source code, including tag keywords and any nested-name-specifiers. The type itself is always 'sugar', used to express what was written in the source code but containing no additional semantic information.") + .attribute("keyword", STRING, "The keyword of this elaborated type, if present. Can be one of: struct, interface, union, class, enum, typename") + .attribute("qualifier", STRING,"The qualifier of this elaborated type, if present (e.g., A::)") + .attribute("namedType", jpRef("type"), "The type that is being prefixed with the qualifier"); + + joinPoint("typedefType").extending("type") + .attribute("decl", jpRef("typedefNameDecl"), "The typedef declaration associated with this typedef type") + .attribute("underlyingType", jpRef("type"), "The type being aliased"); + } +} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/ClavaWeaverResource.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/ClavaWeaverResource.java deleted file mode 100644 index 99202e6be5..0000000000 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/ClavaWeaverResource.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright 2013 SPeCS Research Group. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package pt.up.fe.specs.clava.weaver; - -import pt.up.fe.specs.util.providers.ResourceProvider; - -/** - * @author Joao Bispo - * - */ -public enum ClavaWeaverResource implements ResourceProvider { - JOINPOINTS("joinPointModel.xml"), - ARTIFACTS("artifacts.xml"), - ACTIONS("actionModel.xml"); - - private final String resource; - - private static final String basePackage = "clava/weaverspecs/"; - - /** - * @param resource - */ - private ClavaWeaverResource(String resource) { - this.resource = basePackage + resource; - } - - /* (non-Javadoc) - * @see org.suikasoft.SharedLibrary.Interfaces.ResourceProvider#getResource() - */ - @Override - public String getResource() { - return resource; - } -} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxActions.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxActions.java index 930ee3deca..7be3c44b01 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxActions.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxActions.java @@ -14,6 +14,8 @@ package pt.up.fe.specs.clava.weaver; import com.google.common.base.Preconditions; + +import org.lara.interpreter.weaver.interf.enums.InsertPosition; import org.lara.interpreter.weaver.interf.events.Stage; import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaNodes; @@ -23,7 +25,7 @@ import pt.up.fe.specs.clava.ast.extra.App; import pt.up.fe.specs.clava.ast.stmt.*; import pt.up.fe.specs.clava.utils.NodePosition; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AScope; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; import pt.up.fe.specs.util.SpecsCheck; @@ -63,13 +65,13 @@ public class CxxActions { * @param position * @param from */ - public static AJoinPoint insertAsStmt(ClavaNode target, String code, Insert insert, CxxWeaver weaver) { + public static AJoinpoint insertAsStmt(ClavaNode target, String code, Insert insert, CxxWeaver weaver) { // If target is part of App, clear caches target.getAncestorTry(App.class).ifPresent(app -> { app.clearCache(); weaver.getEventTrigger().triggerAction(Stage.DURING, - "CxxActions.insertAsStmt", - CxxJoinpoints.create(target, weaver), Arrays.asList(insert, code), Optional.empty()); + CxxJoinpoints.create(target, weaver), + "CxxActions.insertAsStmt", Optional.empty(), Arrays.asList(insert, code)); }); // Convert Insert to NodePosition @@ -99,13 +101,13 @@ private static void checkInsertAfterReturn(ClavaNode base, ClavaNode newNode) { } } - public static AJoinPoint[] insertAsChild(String position, ClavaNode base, ClavaNode node, CxxWeaver weaver) { + public static AJoinpoint[] insertAsChild(String position, ClavaNode base, ClavaNode node, CxxWeaver weaver) { // If base is part of App, clear caches base.getAncestorTry(App.class).ifPresent(app -> { app.clearCache(); weaver.getEventTrigger().triggerAction(Stage.DURING, - "CxxActions.insertAsChild", - CxxJoinpoints.create(base, weaver), Arrays.asList(position, CxxJoinpoints.create(node, weaver)), Optional.empty()); + CxxJoinpoints.create(base, weaver), + "CxxActions.insertAsChild", Optional.empty(), Arrays.asList(position, CxxJoinpoints.create(node, weaver))); }); switch (position) { @@ -132,7 +134,7 @@ public static AJoinPoint[] insertAsChild(String position, ClavaNode base, ClavaN // // Remove all children // base.removeChildren(0, base.getNumChildren()); base.addChild(node); - return new AJoinPoint[]{CxxJoinpoints.create(node, weaver)}; + return new AJoinpoint[]{CxxJoinpoints.create(node, weaver)}; default: throw new RuntimeException("Case not defined:" + position); } @@ -156,10 +158,10 @@ public static ClavaNode replace(ClavaNode target, ClavaNode newNode, CxxWeaver w return NodeInsertUtils.replace(target, newNode); } - public static AJoinPoint insertBefore(AJoinPoint baseJp, AJoinPoint newJp, CxxWeaver weaver) { + public static AJoinpoint insertBefore(AJoinpoint baseJp, AJoinpoint newJp, CxxWeaver weaver) { return insert(baseJp, newJp, Insert.BEFORE, (base, node) -> NodeInsertUtils.insertBefore(base, node), weaver); - // Stmt newStmt = ClavaNodes.toStmt(newJp.getNode()); - // Stmt baseStmt = getValidStatement(baseJp.getNode(), Insert.BEFORE); + // Stmt newStmt = ClavaNodes.toStmt(newJp.getNodeImpl()); + // Stmt baseStmt = getValidStatement(baseJp.getNodeImpl(), Insert.BEFORE); // if (baseStmt == null) { // return null; // } @@ -168,14 +170,14 @@ public static AJoinPoint insertBefore(AJoinPoint baseJp, AJoinPoint newJp, CxxWe // return CxxJoinpoints.create(newStmt); } - public static AJoinPoint insertAfter(AJoinPoint baseJp, AJoinPoint newJp, CxxWeaver weaver) { - checkInsertAfterReturn(baseJp.getNode(), newJp.getNode()); + public static AJoinpoint insertAfter(AJoinpoint baseJp, AJoinpoint newJp, CxxWeaver weaver) { + checkInsertAfterReturn(baseJp.getNodeImpl(), newJp.getNodeImpl()); return insert(baseJp, newJp, Insert.AFTER, (base, node) -> NodeInsertUtils.insertAfter(base, node), weaver); // // If inside a scope, treat nodes at the statement level // // if - // Stmt newStmt = ClavaNodes.toStmt(newJp.getNode()); - // Stmt baseStmt = getValidStatement(baseJp.getNode(), Insert.AFTER); + // Stmt newStmt = ClavaNodes.toStmt(newJp.getNodeImpl()); + // Stmt baseStmt = getValidStatement(baseJp.getNodeImpl(), Insert.AFTER); // if (baseStmt == null) { // return null; // } @@ -184,36 +186,36 @@ public static AJoinPoint insertAfter(AJoinPoint baseJp, AJoinPoint newJp, CxxWea // return CxxJoinpoints.create(newStmt); } - public static AJoinPoint insert(AJoinPoint baseJp, - AJoinPoint newJp, Insert position, + public static AJoinpoint insert(AJoinpoint baseJp, + AJoinpoint newJp, Insert position, BiConsumer insertFunction, CxxWeaver weaver) { // Set origin point from target to newNode if locations are invalid and no origin point is set - var newNode = newJp.getNode(); - var target = baseJp.getNode(); + var newNode = newJp.getNodeImpl(); + var target = baseJp.getNodeImpl(); newNode.setOrigin(target); // Special case: if this node is a statement in a loop header, insert using a special function. if (baseJp.getIsInsideLoopHeaderImpl() && (position != Insert.REPLACE && position != Insert.AROUND) - && baseJp.getNode() instanceof Stmt) { + && baseJp.getNodeImpl() instanceof Stmt) { return insertInLoopHeader(baseJp, newJp, position); } // If baseJp will do a statement-base insertion, adapt nodes // Check if base is inside a scope - boolean isInsideScope = baseJp.getNode().getAncestorTry(CompoundStmt.class).isPresent(); + boolean isInsideScope = baseJp.getNodeImpl().getAncestorTry(CompoundStmt.class).isPresent(); - // Optional targetStmt = ClavaNodes.getStatement(baseJp.getNode()); - ClavaNode adaptedBase = isInsideScope ? ClavaNodes.getValidStatement(baseJp.getNode(), position.toPosition()) - : baseJp.getNode(); + // Optional targetStmt = ClavaNodes.getStatement(baseJp.getNodeImpl()); + ClavaNode adaptedBase = isInsideScope ? ClavaNodes.getValidStatement(baseJp.getNodeImpl(), position.toPosition()) + : baseJp.getNodeImpl(); if (adaptedBase == null) { return null; } - ClavaNode adaptedNew = isInsideScope ? ClavaNodes.toStmt(newJp.getNode()) : newJp.getNode(); + ClavaNode adaptedNew = isInsideScope ? ClavaNodes.toStmt(newJp.getNodeImpl()) : newJp.getNodeImpl(); // If adaptedNew is not a comment or a pragma, and we are inserting before, adaptedBase should be the first // comment or pragma associated with current base @@ -229,23 +231,23 @@ public static AJoinPoint insert(AJoinPoint baseJp, // If base is part of App, clear caches adaptedBase.getAncestorTry(App.class).ifPresent(app -> { app.clearCache(); - weaver.getEventTrigger().triggerAction(Stage.DURING, "CxxActions.insert", - baseJp, - Arrays.asList(position, newJp), Optional.ofNullable((Object) returnedJp)); + weaver.getEventTrigger().triggerAction(Stage.DURING, baseJp, + "CxxActions.insert", + Optional.ofNullable((Object) returnedJp), Arrays.asList(position, newJp)); }); return returnedJp; } - private static AJoinPoint insertInLoopHeader(AJoinPoint baseJp, AJoinPoint newJp, Insert position) { + private static AJoinpoint insertInLoopHeader(AJoinpoint baseJp, AJoinpoint newJp, Insert position) { // Check position if (position != Insert.BEFORE && position != Insert.AFTER) { throw new RuntimeException("Insertion position not supported: " + position); } // System.out.println("#ASDASDSAD"); - var baseNode = baseJp.getNode(); - var newNode = newJp.getNode(); + var baseNode = baseJp.getNodeImpl(); + var newNode = newJp.getNodeImpl(); // System.out.println("BASE NODE: " + baseNode.getClass()); // If DeclStmt, insert as new initialization if (baseNode instanceof DeclStmt) { @@ -323,10 +325,10 @@ private static AJoinPoint insertInLoopHeader(AJoinPoint baseJp, AJoinPoint newJp * @param weaver * @return */ - public static AJoinPoint insertJpAsStatement(AJoinPoint baseJp, AJoinPoint newJp, String position, + public static AJoinpoint insertJpAsStatement(AJoinpoint baseJp, AJoinpoint newJp, String position, CxxWeaver weaver) { - AStatement stmtJp = CxxJoinpoints.create(ClavaNodes.toStmt(newJp.getNode()), weaver, AStatement.class); + AStatement stmtJp = CxxJoinpoints.create(ClavaNodes.toStmt(newJp.getNodeImpl()), weaver, AStatement.class); return insertJp(baseJp, stmtJp, position, weaver); } @@ -338,29 +340,29 @@ public static AJoinPoint insertJpAsStatement(AJoinPoint baseJp, AJoinPoint newJp * @param newJpS * @param position */ - public static AJoinPoint insertJp(AJoinPoint baseJp, AJoinPoint newJp, String position, CxxWeaver weaver) { + public static AJoinpoint insertJp(AJoinpoint baseJp, AJoinpoint newJp, String position, CxxWeaver weaver) { // If baseJp is part of App, clear caches - baseJp.getNode().getAncestorTry(App.class).ifPresent(app -> { + baseJp.getNodeImpl().getAncestorTry(App.class).ifPresent(app -> { app.clearCache(); weaver.getEventTrigger().triggerAction(Stage.DURING, - "CxxActions.insertJp", - baseJp, Arrays.asList(position, newJp), Optional.empty()); + baseJp, + "CxxActions.insertJp", Optional.empty(), Arrays.asList(position, newJp)); }); switch (position) { case "before": - var newBase = ClavaNodes.getFirstNodeOfTargetRegion(baseJp.getNode(), newJp.getNode()); - NodeInsertUtils.insertBefore(newBase, newJp.getNode()); + var newBase = ClavaNodes.getFirstNodeOfTargetRegion(baseJp.getNodeImpl(), newJp.getNodeImpl()); + NodeInsertUtils.insertBefore(newBase, newJp.getNodeImpl()); break; case "after": - NodeInsertUtils.insertAfter(baseJp.getNode(), newJp.getNode()); + NodeInsertUtils.insertAfter(baseJp.getNodeImpl(), newJp.getNodeImpl()); break; case "around": case "replace": - weaver.clearUserField(baseJp.getNode()); - NodeInsertUtils.replace(baseJp.getNode(), newJp.getNode()); + weaver.clearUserField(baseJp.getNodeImpl()); + NodeInsertUtils.replace(baseJp.getNodeImpl(), newJp.getNodeImpl()); break; default: @@ -370,25 +372,24 @@ public static AJoinPoint insertJp(AJoinPoint baseJp, AJoinPoint newJp, String po return newJp; } - public static void insertStmt(String position, Stmt body, Stmt stmt, CxxWeaver weaver) { + public static void insertStmt(InsertPosition position, Stmt body, Stmt stmt, CxxWeaver weaver) { Preconditions.checkArgument(body instanceof CompoundStmt); // If body is part of App, clear caches body.getAncestorTry(App.class).ifPresent(app -> { app.clearCache(); weaver.getEventTrigger().triggerAction(Stage.DURING, - "CxxActions.insertStmt", - CxxJoinpoints.create(body, weaver), Arrays.asList(position, CxxJoinpoints.create(stmt, weaver)), Optional.empty()); + CxxJoinpoints.create(body, weaver), + "CxxActions.insertStmt", Optional.empty(), Arrays.asList(position, CxxJoinpoints.create(stmt, weaver))); }); switch (position) { - case "before": + case BEFORE: // Insert before all statements in body body.addChild(0, stmt); break; - case "after": - + case AFTER: if (body.hasChildren()) { checkInsertAfterReturn(body.getChild(body.getNumChildren() - 1), stmt); } @@ -396,8 +397,7 @@ public static void insertStmt(String position, Stmt body, Stmt stmt, CxxWeaver w body.addChild(stmt); break; - case "around": - case "replace": + case REPLACE: // Remove all children removeChildren(body, weaver); // Add given statement @@ -413,8 +413,8 @@ public static void removeChildren(ClavaNode node, CxxWeaver weaver) { node.getAncestorTry(App.class).ifPresent(app -> { app.clearCache(); weaver.getEventTrigger().triggerAction(Stage.DURING, - "CxxActions.removeChildren", - CxxJoinpoints.create(node, weaver), Collections.emptyList(), Optional.empty()); + CxxJoinpoints.create(node, weaver), + "CxxActions.removeChildren", Optional.empty(), Collections.emptyList()); }); // Clear use fields @@ -426,11 +426,11 @@ public static void removeChildren(ClavaNode node, CxxWeaver weaver) { node.removeChildren(0, node.getNumChildren()); } - public static AJoinPoint insertReturn(AScope scope, AJoinPoint code, CxxWeaver weaver) { + public static AJoinpoint insertReturn(AScope scope, AJoinpoint code, CxxWeaver weaver) { // Does not take into account situations where functions returns in all paths of an if/else. // This means it can lead to dead-code, although for C/C++ that does not seem to be problematic. - List bodyStmts = ((CompoundStmt) scope.getNode()).toStatements(); + List bodyStmts = ((CompoundStmt) scope.getNodeImpl()).toStatements(); // Check if it has return statement, ignoring wrapper statements Stmt lastStmt = SpecsCollections.reverseStream(bodyStmts) @@ -446,14 +446,14 @@ public static AJoinPoint insertReturn(AScope scope, AJoinPoint code, CxxWeaver w .map(ReturnStmt.class::cast) .collect(Collectors.toList()); - AJoinPoint lastInsertPoint = null; + AJoinpoint lastInsertPoint = null; if (lastReturnStmt != null) { returnStatements = SpecsCollections.concat(returnStatements, lastReturnStmt); } for (ReturnStmt returnStmt : returnStatements) { - AJoinPoint returnJp = CxxJoinpoints.create(returnStmt, weaver); + AJoinpoint returnJp = CxxJoinpoints.create(returnStmt, weaver); lastInsertPoint = returnJp.insertBeforeImpl(code); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxAttributes.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxAttributes.java index bb51427241..a3edcb830d 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxAttributes.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxAttributes.java @@ -28,9 +28,8 @@ import pt.up.fe.specs.clava.ast.stmt.CompoundStmt; import pt.up.fe.specs.clava.ast.stmt.LoopStmt; import pt.up.fe.specs.clava.utils.StmtWithCondition; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.enums.AExpressionUseEnum; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; +import pt.up.fe.specs.clava.weaver.enums.ExpressionUse; public class CxxAttributes { @@ -164,7 +163,7 @@ public static Optional getParentRegion(ClavaNode node) { // Get current region Optional currentRegionTry = getCurrentRegion(node); if (!currentRegionTry.isPresent()) { - // ClavaLog.info("Join point '" + getJoinPointType() + "' does not support parentRegion"); + // ClavaLog.info("Join point '" + joinPointType() + "' does not support parentRegion"); return Optional.empty(); } @@ -187,14 +186,14 @@ public static Optional getParentRegion(ClavaNode node) { // return CxxJoinpoints.create(getCurrentRegion(currentRegion.getParent()), this); } - public static String convertUse(ExprUse use) { + public static ExpressionUse convertUse(ExprUse use) { switch (use) { case READ: - return AExpressionUseEnum.READ.getName(); + return ExpressionUse.READ; case WRITE: - return AExpressionUseEnum.WRITE.getName(); + return ExpressionUse.WRITE; case READWRITE: - return AExpressionUseEnum.READWRITE.getName(); + return ExpressionUse.READWRITE; default: throw new RuntimeException("Case not defined:" + use); } @@ -246,18 +245,17 @@ public static Object fromLara(Object value) { // Special cases // If join point , convert to Clava node - if (value instanceof AJoinPoint) { - return ((ACxxWeaverJoinPoint) value).getNode(); + if (value instanceof AJoinpoint jp) { + return jp.getNodeImpl(); } // If CxxWeaverDataClass, unwrap to conventional DataClass - if (value instanceof CxxWeaverDataClass) { - return ((CxxWeaverDataClass) value).getOriginalData(); + if (value instanceof CxxWeaverDataClass weaverDataClass) { + return weaverDataClass.getOriginalData(); } // If a List, apply adapt over all elements of the list - if (value instanceof List) { - var valueList = (List) value; + if (value instanceof List valueList) { var newValue = new ArrayList(valueList.size()); for (var valueElement : valueList) { diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxJoinpoints.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxJoinpoints.java index 4c9aec82d9..2862cc436e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxJoinpoints.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxJoinpoints.java @@ -31,8 +31,7 @@ import pt.up.fe.specs.clava.ast.stmt.*; import pt.up.fe.specs.clava.ast.type.*; import pt.up.fe.specs.clava.utils.NullNode; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.joinpoints.*; import pt.up.fe.specs.clava.weaver.joinpoints.cilk.CxxCilkFor; import pt.up.fe.specs.clava.weaver.joinpoints.cilk.CxxCilkSpawn; @@ -48,7 +47,7 @@ public class CxxJoinpoints { - private static final BiFunctionClassMap JOINPOINT_FACTORY; + private static final BiFunctionClassMap> JOINPOINT_FACTORY; static { JOINPOINT_FACTORY = new BiFunctionClassMap<>(); @@ -59,7 +58,7 @@ public class CxxJoinpoints { JOINPOINT_FACTORY.put(UnaryOperator.class, CxxUnaryOp::new); JOINPOINT_FACTORY.put(ConditionalOperator.class, CxxTernaryOp::new); JOINPOINT_FACTORY.put(CXXMemberCallExpr.class, CxxMemberCall::new); - JOINPOINT_FACTORY.put(CUDAKernelCallExpr.class, CXXCudaKernelCall::new); + JOINPOINT_FACTORY.put(CUDAKernelCallExpr.class, CxxCudaKernelCall::new); JOINPOINT_FACTORY.put(CallExpr.class, CxxCall::new); JOINPOINT_FACTORY.put(DeclRefExpr.class, CxxVarref::new); JOINPOINT_FACTORY.put(ArraySubscriptExpr.class, CxxArrayAccess::new); @@ -139,37 +138,37 @@ public class CxxJoinpoints { JOINPOINT_FACTORY.put(CilkFor.class, CxxCilkFor::new); JOINPOINT_FACTORY.put(CilkSync.class, CxxCilkSync::new); JOINPOINT_FACTORY.put(CilkSpawn.class, CxxCilkSpawn::new); - JOINPOINT_FACTORY.put(TagDeclVars.class, GenericJoinpoint::new); + JOINPOINT_FACTORY.put(TagDeclVars.class, CxxJoinpoint::new); JOINPOINT_FACTORY.put(ClavaNode.class, CxxJoinpoints::defaultFactory); } - private static ACxxWeaverJoinPoint nullNode(ClavaNode node, CxxWeaver weaver) { + private static AJoinpoint nullNode(ClavaNode node, CxxWeaver weaver) { SpecsCheck.checkArgument(node instanceof NullNode, () -> "Expected an instance of NullNode, received: " + node); return null; } - private static ACxxWeaverJoinPoint compoundStmtFactory(CompoundStmt stmt, CxxWeaver weaver) { + private static AJoinpoint compoundStmtFactory(CompoundStmt stmt, CxxWeaver weaver) { // If no parent, use Scope as default if (!stmt.hasParent()) { - return new CxxScope(stmt, weaver); + return new CxxScope<>(stmt, weaver); } // If CompoundStmt parent is another CompoundStmt, is a Scope. if (stmt.getParent() instanceof CompoundStmt) { - return new CxxScope(stmt, weaver); + return new CxxScope<>(stmt, weaver); } // Otherwise, is a Body - return new CxxBody(stmt, weaver); + return new CxxBody<>(stmt, weaver); } - private static ACxxWeaverJoinPoint defaultFactory(ClavaNode node, CxxWeaver weaver) { + private static AJoinpoint defaultFactory(ClavaNode node, CxxWeaver weaver) { SpecsLogs.warn("Factory not defined for nodes of class '" + node.getClass().getSimpleName() + "'"); - return new GenericJoinpoint(node, weaver); + return new CxxJoinpoint<>(node, weaver); } - public static ACxxWeaverJoinPoint createFromLara(Object node, CxxWeaver weaver) { + public static AJoinpoint createFromLara(Object node, CxxWeaver weaver) { if (!(node instanceof ClavaNode)) { throw new RuntimeException( "Expected input to be a ClavaNode, is " + node.getClass().getSimpleName() + ": " + node); @@ -178,7 +177,7 @@ public static ACxxWeaverJoinPoint createFromLara(Object node, CxxWeaver weaver) return create((ClavaNode) node, weaver); } - public static ACxxWeaverJoinPoint create(ClavaNode node, CxxWeaver weaver) { + public static AJoinpoint create(ClavaNode node, CxxWeaver weaver) { if (node == null) { ClavaLog.debug("CxxJoinpoints: tried to create join point from null node, returning undefined"); return null; @@ -187,7 +186,7 @@ public static ACxxWeaverJoinPoint create(ClavaNode node, CxxWeaver weaver) { return JOINPOINT_FACTORY.apply(node, weaver); } - public static T create(ClavaNode node, CxxWeaver weaver, Class targetClass) { + public static > T create(ClavaNode node, CxxWeaver weaver, Class targetClass) { if (targetClass == null) { throw new RuntimeException("Check if you meant to call 'create' with a single argument"); } @@ -195,24 +194,24 @@ public static T create(ClavaNode node, CxxWeaver weaver, return targetClass.cast(create(node, weaver)); } - public static T[] create(List nodes, CxxWeaver weaver, Class targetClass) { + public static > T[] create(List nodes, CxxWeaver weaver, Class targetClass) { return nodes.stream() .map(node -> create(node, weaver, targetClass)) .toArray(size -> SpecsCollections.newArray(targetClass, size)); } - public static CxxProgram getProgram(AJoinPoint joinpoint) { - AJoinPoint currentJp = joinpoint; + public static CxxProgram getProgram(AJoinpoint joinpoint) { + AJoinpoint currentJp = joinpoint; while (currentJp.getHasParentImpl()) { currentJp = currentJp.getParentImpl(); } // Check that root node is a CxxProgram - if (!(currentJp instanceof CxxProgram)) { - throw new RuntimeException("Expected root node to be of type '" + CxxProgram.class + "'"); + if (currentJp instanceof CxxProgram program) { + return program; } - return (CxxProgram) currentJp; + throw new RuntimeException("Expected root node to be of type '" + CxxProgram.class + "'"); } /** @@ -221,8 +220,8 @@ public static CxxProgram getProgram(AJoinPoint joinpoint) { * @param joinpointClass * @return */ - public static Optional getAncestorandSelf(AJoinPoint joinpoint, Class joinpointClass) { - AJoinPoint currentJp = joinpoint; + public static > Optional getAncestorandSelf(AJoinpoint joinpoint, Class joinpointClass) { + AJoinpoint currentJp = joinpoint; if (joinpointClass.isInstance(currentJp)) { return Optional.of(joinpointClass.cast(currentJp)); @@ -239,7 +238,7 @@ public static Optional getAncestorandSelf(AJoinPoint j return Optional.empty(); } - public static CxxWeaver getWeaver(AJoinPoint joinpoint) { + public static CxxWeaver getWeaver(AJoinpoint joinpoint) { // Get root joinpoint (program) return getProgram(joinpoint).getWeaverEngine(); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxSelects.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxSelects.java index a9d654354a..ff6a259fb2 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxSelects.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxSelects.java @@ -14,7 +14,6 @@ package pt.up.fe.specs.clava.weaver; import java.util.List; -import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -26,25 +25,24 @@ import pt.up.fe.specs.clava.ast.stmt.Stmt; import pt.up.fe.specs.clava.ast.stmt.WrapperStmt; import pt.up.fe.specs.clava.utils.NullNode; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.joinpoints.CxxArrayAccess; +import pt.up.fe.specs.util.SpecsCollections; public class CxxSelects { /** - * Method that helps selecting join points. + * Selects join points. + * * * @param targetJoinpoint * @param directChildren * @param selectDescendents * @param filter - * @param mapper * @return */ - private static List selectPrivate(Class targetJoinpoint, - List directChildren, boolean selectDescendents, Predicate filter, - Function mapper) { + public static > T[] select(CxxWeaver weaver, Class targetJoinpoint, + List directChildren, boolean selectDescendents, Predicate filter) { Stream currentStream = directChildren.stream(); if (selectDescendents) { @@ -52,31 +50,13 @@ private static List selectPrivate(C } return currentStream.filter(filter) - .map(mapper) + .map(node -> CxxJoinpoints.create(node, weaver, targetJoinpoint)) // Filter null join points .filter(jp -> jp != null) - .collect(Collectors.toList()); - } - - /** - * Selects join points. - * - * - * @param targetJoinpoint - * @param directChildren - * @param selectDescendents - * @param filter - * @return - */ - public static List select(CxxWeaver weaver, Class targetJoinpoint, - List directChildren, boolean selectDescendents, Predicate filter) { - - return selectPrivate(targetJoinpoint, directChildren, selectDescendents, filter, - node -> CxxJoinpoints.create(node, weaver, targetJoinpoint)); - + .toArray(size -> SpecsCollections.newArray(targetJoinpoint, size)); } - public static List select(CxxWeaver weaver, Class targetJoinpoint, + public static > T[] select(CxxWeaver weaver, Class targetJoinpoint, List directChildren, boolean selectDescendents, Class filter) { return select(weaver, targetJoinpoint, directChildren, selectDescendents, filter::isInstance); @@ -106,35 +86,32 @@ public static boolean stmtFilter(ClavaNode node) { return true; } - // public static AJoinPoint[] selectedNodesToJps(List selectedNodes, WeaverEngine weaverEngine) - // { - // return selectedNodesToJps(selectedNodes.stream(), jp -> true, weaverEngine); - // } - - public static AJoinPoint[] selectedNodesToJps(Stream selectedNodes, + public static AJoinpoint[] selectedNodesToJps(Stream selectedNodes, CxxWeaver weaverEngine) { return selectedNodesToJps(selectedNodes, jp -> true, weaverEngine); } - public static AJoinPoint[] selectedNodesToJps(Stream selectedNodes, - Predicate filter, CxxWeaver weaverEngine) { + @SuppressWarnings("unchecked") + public static > T[] selectedNodesToJps(Stream selectedNodes, + Predicate filter, CxxWeaver weaverEngine) { return selectedNodesToJpsStream(selectedNodes, filter, weaverEngine) + // Collect to list first, to avoid issues with generic array creation .collect(Collectors.toList()) - // .toArray(new AJoinPoint[0]); - .toArray(AJoinPoint[]::new); + .toArray(size -> (T[]) new AJoinpoint[size]); } - public static Stream selectedNodesToJpsStream(Stream selectedNodes, + public static Stream> selectedNodesToJpsStream(Stream selectedNodes, CxxWeaver weaverEngine) { return selectedNodesToJpsStream(selectedNodes, jp -> true, weaverEngine); } - public static Stream selectedNodesToJpsStream(Stream selectedNodes, - Predicate filter, CxxWeaver weaverEngine) { + @SuppressWarnings("unchecked") + public static > Stream selectedNodesToJpsStream(Stream selectedNodes, + Predicate filter, CxxWeaver weaverEngine) { - var selectedJps = selectedNodes + return selectedNodes // Ignore null nodes .filter(sibling -> !(sibling instanceof NullNode)) .map(node -> CxxJoinpoints.create(node, weaverEngine)) @@ -142,19 +119,16 @@ public static Stream selectedNodesToJpsStream(Stream jp != null) // Default filter .filter(CxxSelects::defaultSelectFilter) - .filter(jp -> filter.test(jp)) - // Cast back to AJoinPoint - .map(jp -> (AJoinPoint) jp); - - return selectedJps; + .map(jp -> (T) jp) + .filter(filter); } - private static boolean defaultSelectFilter(AJoinPoint jp) { + private static boolean defaultSelectFilter(AJoinpoint jp) { // TODO: If more cases, use a ClassMap instead // If ArraySubscript, return only if top-level if (jp instanceof CxxArrayAccess) { - return ((ArraySubscriptExpr) jp.getNode()).isTopLevel(); + return ((ArraySubscriptExpr) jp.getNodeImpl()).isTopLevel(); } return true; diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaver.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaver.java index 58926c96cd..ee675b71f5 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaver.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaver.java @@ -3,10 +3,8 @@ import org.lara.interpreter.joptions.config.interpreter.LaraiKeys; import org.lara.interpreter.weaver.ast.AstMethods; import org.lara.interpreter.weaver.interf.AGear; -import org.lara.interpreter.weaver.interf.JoinPoint; import org.lara.interpreter.weaver.interf.events.Stage; import org.lara.interpreter.weaver.options.WeaverOption; -import org.lara.language.specification.dsl.LanguageSpecification; import org.suikasoft.jOptions.Interfaces.DataStore; import org.suikasoft.jOptions.storedefinition.StoreDefinition; import org.suikasoft.jOptions.storedefinition.StoreDefinitionBuilder; @@ -27,6 +25,7 @@ import pt.up.fe.specs.clava.language.Standard; import pt.up.fe.specs.clava.parsing.snippet.SnippetParser; import pt.up.fe.specs.clava.utils.SourceType; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.weaver.ACxxWeaver; import pt.up.fe.specs.clava.weaver.gears.CacheHandlerGear; import pt.up.fe.specs.clava.weaver.gears.ModifiedFilesGear; @@ -53,7 +52,7 @@ * implementation should be done by extending those * abstract classes with user-defined classes.
    * The abstract class - * {@link pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint} can be used + * {@link pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint} can be used * to add user-defined * methods and fields which the user intends to add for all join points and are * not intended to be used in LARA aspects. @@ -62,11 +61,6 @@ */ public class CxxWeaver extends ACxxWeaver { - public static LanguageSpecification buildLanguageSpecification() { - return LanguageSpecification.newInstance(ClavaWeaverResource.JOINPOINTS, ClavaWeaverResource.ARTIFACTS, - ClavaWeaverResource.ACTIONS); - } - private static final List CLAVA_PREDEFINED_EXTERNAL_DEPS = Arrays.asList("LAT - Lara Autotuning Tool", "https://github.com/specs-feup/LAT-Lara-Autotuning-Tool.git", "Benchmark - CHStone (import lara.benchmark.CHStoneBenchmarkSet)", @@ -214,8 +208,8 @@ public Optional getAppTry() { return weaverData.getAst(); } - public CxxProgram getAppJp() { - return new CxxProgram(getApp(), this); + public CxxProgram getAppJp() { + return new CxxProgram<>(getApp(), this); } private Map> getUserValues() { @@ -741,7 +735,7 @@ private static Optional headerFlagToFile(String headerFlag) { * @return an instance of the join point root/program */ @Override - public JoinPoint getRootJp() { + public AJoinpoint getRootJp() { return CxxJoinpoints.create(getApp(), this); } @@ -1106,8 +1100,8 @@ public TranslationUnit rebuildFile(TranslationUnit tUnit) { // After rebuilding, clear current app cache getApp().clearCache(); getEventTrigger().triggerAction(Stage.DURING, - "CxxWeaver.rebuildFile", - CxxJoinpoints.create(tUnit, this), Collections.emptyList(), Optional.empty()); + CxxJoinpoints.create(tUnit, this), + "CxxWeaver.rebuildFile", Optional.empty(), Collections.emptyList()); // Return correct TranslationUnit for (TranslationUnit tu : rebuiltApp.getTranslationUnits()) { @@ -1536,11 +1530,6 @@ private void obtainFiles(File folder, File baseFolder, Map processed allFiles.stream().forEach(filename -> processedFiles.put(new File(filename), baseFolder)); } - @Override - protected LanguageSpecification buildLangSpecs() { - return buildLanguageSpecification(); - } - @Override public List getPredefinedExternalDependencies() { return SpecsCollections.concatList(super.getPredefinedExternalDependencies(), CLAVA_PREDEFINED_EXTERNAL_DEPS); diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaverApi.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaverApi.java index 3b8edfa14b..9c2512ea08 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaverApi.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/CxxWeaverApi.java @@ -19,12 +19,12 @@ import java.util.stream.Collectors; import pt.up.fe.specs.clava.ast.extra.App; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AInclude; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; public class CxxWeaverApi { - public static ACxxWeaverJoinPoint findJp(CxxWeaver weaver, String filepath, String astId) { + public static AJoinpoint findJp(CxxWeaver weaver, String filepath, String astId) { // Get AST at the top of the stack App topAst = weaver.getApp(); diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AExpressionUseEnum.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AExpressionUseEnum.java deleted file mode 100644 index 55295087e0..0000000000 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AExpressionUseEnum.java +++ /dev/null @@ -1,26 +0,0 @@ -package pt.up.fe.specs.clava.weaver.abstracts.joinpoints.enums; - -import org.lara.interpreter.weaver.interf.NamedEnum; - -/** - * - */ -public enum AExpressionUseEnum implements NamedEnum{ - READ("read"), - WRITE("write"), - READWRITE("readwrite"); - private String name; - - /** - * - */ - private AExpressionUseEnum(String name){ - this.name = name; - } - /** - * - */ - public String getName() { - return name; - } -} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AFunctionStorageClassEnum.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AFunctionStorageClassEnum.java deleted file mode 100644 index d4a4a61d8d..0000000000 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AFunctionStorageClassEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package pt.up.fe.specs.clava.weaver.abstracts.joinpoints.enums; - -import org.lara.interpreter.weaver.interf.NamedEnum; - -/** - * - */ -public enum AFunctionStorageClassEnum implements NamedEnum{ - NONE("none"), - AUTO("auto"), - EXTERN("extern"), - PRIVATE_EXTERN("private_extern"), - REGISTER("register"), - STATIC("static"); - private String name; - - /** - * - */ - private AFunctionStorageClassEnum(String name){ - this.name = name; - } - /** - * - */ - public String getName() { - return name; - } -} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/ALoopKindEnum.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/ALoopKindEnum.java deleted file mode 100644 index 132f73b5e2..0000000000 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/ALoopKindEnum.java +++ /dev/null @@ -1,27 +0,0 @@ -package pt.up.fe.specs.clava.weaver.abstracts.joinpoints.enums; - -import org.lara.interpreter.weaver.interf.NamedEnum; - -/** - * - */ -public enum ALoopKindEnum implements NamedEnum{ - FOR("for"), - WHILE("while"), - DOWHILE("dowhile"), - FOREACH("foreach"); - private String name; - - /** - * - */ - private ALoopKindEnum(String name){ - this.name = name; - } - /** - * - */ - public String getName() { - return name; - } -} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AWrapperStmtKindEnum.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AWrapperStmtKindEnum.java deleted file mode 100644 index b749c6bc2d..0000000000 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/joinpoints/enums/AWrapperStmtKindEnum.java +++ /dev/null @@ -1,25 +0,0 @@ -package pt.up.fe.specs.clava.weaver.abstracts.joinpoints.enums; - -import org.lara.interpreter.weaver.interf.NamedEnum; - -/** - * - */ -public enum AWrapperStmtKindEnum implements NamedEnum{ - COMMENT("comment"), - PRAGMA("pragma"); - private String name; - - /** - * - */ - private AWrapperStmtKindEnum(String name){ - this.name = name; - } - /** - * - */ - public String getName() { - return name; - } -} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/actions/CallWrap.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/actions/CallWrap.java index abcd5ffece..3c35eb5214 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/actions/CallWrap.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/actions/CallWrap.java @@ -65,18 +65,18 @@ public class CallWrap { private static final String WRAPPERS_FOLDERNAME = "clava_wrappers"; - private final CxxCall cxxCall; - private final CxxProgram app; + private final CxxCall cxxCall; + private final CxxProgram app; private final ClavaFactory factory; private final CxxWeaver weaver; - public CallWrap(CxxWeaver cxxWeaver, CxxCall cxxCall) { + public CallWrap(CxxWeaver cxxWeaver, CxxCall cxxCall) { this.weaver = cxxWeaver; this.cxxCall = cxxCall; - app = (CxxProgram) cxxCall.getRootImpl(); + app = (CxxProgram) cxxCall.getRootImpl(); - factory = app.getNode().getFactory(); + factory = app.getNodeImpl().getFactory(); } public void addWrapper(String name) { @@ -102,12 +102,12 @@ public void addWrapper(String name) { break; case NO_INCLUDE: addWrapperFunctionInPlace(name, false); - cxxCall.setName(name); // need to call this here before returning + cxxCall.setNameImpl(name); // need to call this here before returning return; case DECLARATION_IN_IMPLEMENTATION: addWrapperFunctionInPlace(name, true); - cxxCall.setName(name); + cxxCall.setNameImpl(name); return; } @@ -116,10 +116,10 @@ public void addWrapper(String name) { // Add include String includePath = getHeaderFile().getRelativeFilepath(); - cxxCall.getNode().getAncestor(TranslationUnit.class).addInclude(includePath, false); + cxxCall.getNodeImpl().getAncestor(TranslationUnit.class).addInclude(includePath, false); // Set call name - cxxCall.setName(name); + cxxCall.setNameImpl(name); } /** @@ -131,7 +131,7 @@ public void addWrapper(String name) { private void createUserIncludeWrapper(String name) { // Get declaration of function call - FunctionDecl declaration = (FunctionDecl) cxxCall.getDeclarationImpl().getNode(); + FunctionDecl declaration = (FunctionDecl) cxxCall.getDeclarationImpl().getNodeImpl(); // Get include file TranslationUnit includeFile = declaration.getAncestor(TranslationUnit.class); @@ -178,7 +178,7 @@ private void addWrapperFunction(String name, FunctionDecl declaration) { */ private void addWrapperFunctionInPlace(String name, boolean hasDecl) { - FunctionDecl originalDefinition = (FunctionDecl) cxxCall.getDefinitionImpl().getNode(); + FunctionDecl originalDefinition = (FunctionDecl) cxxCall.getDefinitionImpl().getNodeImpl(); FunctionDecl wrapperFunctionDeclImpl = (FunctionDecl) originalDefinition.copy(); wrapperFunctionDeclImpl.setDeclName(name); @@ -194,7 +194,7 @@ private void addWrapperFunctionInPlace(String name, boolean hasDecl) { // add to original file TranslationUnit originalFile = originalDefinition.getAncestor(TranslationUnit.class); - TranslationUnit updatedFile = cxxCall.getNode().getApp().getTranslationUnit(originalFile.getLocation()); + TranslationUnit updatedFile = cxxCall.getNodeImpl().getApp().getTranslationUnit(originalFile.getLocation()); // adds the wrapper implementation after the implementation of the original int originalDefinitionIndex = getIndex(originalDefinition, updatedFile); @@ -205,7 +205,7 @@ private void addWrapperFunctionInPlace(String name, boolean hasDecl) { forwardDecl.getBody().get().detach(); if (hasDecl) { // ... after the declaration of the original - FunctionDecl originalDeclaration = (FunctionDecl) cxxCall.getDeclarationImpl().getNode(); + FunctionDecl originalDeclaration = (FunctionDecl) cxxCall.getDeclarationImpl().getNodeImpl(); int originalDeclarationIndex = getIndex(originalDeclaration, updatedFile); updatedFile.addChild(originalDeclarationIndex + 1, forwardDecl); } else { @@ -265,9 +265,9 @@ private void createSystemIncludeWrapper(String name) { private CallWrapType getWrapType() { // Get declaration of function call - AFunction functionDeclJp = cxxCall.getDeclarationImpl(); - AFunction functionDefJp = cxxCall.getDefinitionImpl(); - // AJoinPoint functionDeclJp = cxxCall.getDeclImpl(); + AFunction functionDeclJp = cxxCall.getDeclarationImpl(); + AFunction functionDefJp = cxxCall.getDefinitionImpl(); + // AJoinpoint functionDeclJp = cxxCall.getDeclImpl(); // If no declaration join point is found, this probably means that the call is from // a system header. Currently we cannot know a system include from a function call, @@ -283,25 +283,25 @@ private CallWrapType getWrapType() { // If definition but no declaration, check if it is associated with a File. If not, consider it a system // header function - if (functionDefJp.getNode().getAncestorTry(TranslationUnit.class).isEmpty()) { + if (functionDefJp.getNodeImpl().getAncestorTry(TranslationUnit.class).isEmpty()) { return CallWrapType.SYSTEM_INCLUDE; } // If no declaration but definition is present, this most likely indicates that the function is defined in // the // file of the function call - FunctionDecl funcDef = (FunctionDecl) functionDefJp.getNode(); + FunctionDecl funcDef = (FunctionDecl) functionDefJp.getNodeImpl(); SpecsLogs.msgLib("Could not find declaration of function '" + funcDef.getDeclName() + "' at " + funcDef.getLocation()); return CallWrapType.NO_INCLUDE; } - FunctionDecl functionDecl = (FunctionDecl) functionDeclJp.getNode(); + FunctionDecl functionDecl = (FunctionDecl) functionDeclJp.getNodeImpl(); // Get include file of declaration // FunctionDecl declaration = declarationTry.get(); - FunctionDecl declaration = (FunctionDecl) functionDeclJp.getNode(); + FunctionDecl declaration = (FunctionDecl) functionDeclJp.getNodeImpl(); Optional includeFileTry = declaration.getAncestorTry(TranslationUnit.class); // TODO: Confirm with Pedro what should be done here @@ -331,24 +331,24 @@ private void initClavaWrappers() { // If wrapper files do not exist, create them String implementationFilename = getImplFilename(); - Optional wrapperImpl = app.getNode().getFile(implementationFilename); + Optional wrapperImpl = app.getNodeImpl().getFile(implementationFilename); if (!wrapperImpl.isPresent()) { // Ensure the header file does not exit yet - Preconditions.checkArgument(!app.getNode().getFile(WRAPPER_H_FILENAME).isPresent(), + Preconditions.checkArgument(!app.getNodeImpl().getFile(WRAPPER_H_FILENAME).isPresent(), "Expected header file to not exist yet"); // Create implementation and header file - AFile implFile = AstFactory.file(this.weaver, implementationFilename, WRAPPERS_FOLDERNAME); - AFile headerFile = AstFactory.file(this.weaver, WRAPPER_H_FILENAME, WRAPPERS_FOLDERNAME); + AFile implFile = AstFactory.file(this.weaver, implementationFilename, WRAPPERS_FOLDERNAME); + AFile headerFile = AstFactory.file(this.weaver, WRAPPER_H_FILENAME, WRAPPERS_FOLDERNAME); app.addFileImpl(headerFile); app.addFileImpl(implFile); } // Ensure the header file also exists - Preconditions.checkArgument(app.getNode().getFile(WRAPPER_H_FILENAME).isPresent(), + Preconditions.checkArgument(app.getNodeImpl().getFile(WRAPPER_H_FILENAME).isPresent(), "Expected header file to exist"); return; @@ -362,16 +362,16 @@ private String getImplFilename() { } private List getWrapperIncludesFromFile() { - TranslationUnit callFile = cxxCall.getNode().getAncestor(TranslationUnit.class); + TranslationUnit callFile = cxxCall.getNodeImpl().getAncestor(TranslationUnit.class); return TreeNodeUtils.copy(callFile.getIncludes().getIncludes()); } private FunctionType getFunctionType() { - return cxxCall.getNode().getCalleeDeclRef().getType().toTry(FunctionType.class).get(); + return cxxCall.getNodeImpl().getCalleeDeclRef().getType().toTry(FunctionType.class).get(); } private List createFunctionCallCode(List paramNames) { - CallExpr call = cxxCall.getNode(); + CallExpr call = cxxCall.getNodeImpl(); List wrapperStmts = new ArrayList<>(); @@ -430,7 +430,7 @@ private TranslationUnit getImplementationFile() { // Make sure Clava wrapper files exist initClavaWrappers(); - return app.getNode().getFile(getImplFilename()).orElseThrow(() -> new RuntimeException( + return app.getNodeImpl().getFile(getImplFilename()).orElseThrow(() -> new RuntimeException( "Implementation file not found, make sure init function was called")); } @@ -439,7 +439,7 @@ private TranslationUnit getHeaderFile() { // Make sure Clava wrapper files exist initClavaWrappers(); - return app.getNode().getFile(WRAPPER_H_FILENAME).orElseThrow(() -> new RuntimeException( + return app.getNodeImpl().getFile(WRAPPER_H_FILENAME).orElseThrow(() -> new RuntimeException( "Header file not found, make sure init function was called")); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/enums/InitializationStyle.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/enums/InitializationStyle.java deleted file mode 100644 index 3b05d9d8a7..0000000000 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/enums/InitializationStyle.java +++ /dev/null @@ -1,46 +0,0 @@ -package pt.up.fe.specs.clava.weaver.enums; - -import org.lara.interpreter.weaver.interf.NamedEnum; -import pt.up.fe.specs.util.lazy.Lazy; -import pt.up.fe.specs.util.enums.EnumHelperWithValue; - -/** - * - * - * @author Lara C. - */ -public enum InitializationStyle implements NamedEnum{ - NO_INIT("no_init"), - CINIT("cinit"), - CALL_INIT("call_init"), - LIST_INIT("list_init"); - private String name; - private static final Lazy> ENUM_HELPER = EnumHelperWithValue.newLazyHelperWithValue(InitializationStyle.class); - - /** - * - */ - private InitializationStyle(String name){ - this.name = name; - } - /** - * - */ - public String getName() { - return this.name; - } - - /** - * - */ - public String toString() { - return getName(); - } - - /** - * - */ - public static EnumHelperWithValue getHelper() { - return ENUM_HELPER.get(); - } -} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/gears/ModifiedFilesGear.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/gears/ModifiedFilesGear.java index 0e9e134fa2..b605291af6 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/gears/ModifiedFilesGear.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/gears/ModifiedFilesGear.java @@ -22,7 +22,7 @@ import org.lara.interpreter.weaver.interf.AGear; import org.lara.interpreter.weaver.interf.events.data.ActionEvent; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.joinpoints.CxxFile; import pt.up.fe.specs.clava.weaver.joinpoints.CxxProgram; @@ -47,17 +47,17 @@ public void onAction(ActionEvent data) { } // System.out.println("ACTION THAT CHANGES AST:" + data.getActionName()); - // All join points are AJoinPoint instances - AJoinPoint jp = (AJoinPoint) data.getJoinPoint(); + // All join points are AJoinpoint instances + AJoinpoint jp = (AJoinpoint) data.getJoinPoint(); // If join point 'program', automatically mark all files as modified if (jp instanceof CxxProgram) { - ((CxxProgram) jp).getNode().getFiles().stream().forEach(modifiedFiles::add); + ((CxxProgram) jp).getNodeImpl().getFiles().stream().forEach(modifiedFiles::add); return; } // Store file of this join point - CxxFile fileJp = (CxxFile) jp.getAncestorImpl("file"); + CxxFile fileJp = (CxxFile) jp.getGetAncestorImpl("file"); if (fileJp == null) { return; } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/AstFactory.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/AstFactory.java index fa8d4db2b8..df96d1bb6d 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/AstFactory.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/AstFactory.java @@ -33,7 +33,6 @@ import pt.up.fe.specs.clava.utils.Typable; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.*; import pt.up.fe.specs.clava.weaver.joinpoints.CxxFunction; import pt.up.fe.specs.util.SpecsLogs; @@ -56,10 +55,10 @@ public class AstFactory { * @param joinpoint * @return */ - public static AJoinPoint varDecl(CxxWeaver weaver, String varName, AJoinPoint init) { + public static AJoinpoint varDecl(CxxWeaver weaver, String varName, AJoinpoint init) { // Check that init is an expression - ClavaNode expr = init.getNode(); + ClavaNode expr = init.getNodeImpl(); if (!(expr instanceof Expr)) { SpecsLogs.msgInfo("CxxFactory.varDecl: parameter 'init' must be of type expression, it is of type '" + expr.getNodeName() + "'"); @@ -68,7 +67,7 @@ public static AJoinPoint varDecl(CxxWeaver weaver, String varName, AJoinPoint in Expr initExpr = (Expr) expr; - Type initType = (Type) init.getTypeImpl().getNode(); + Type initType = (Type) init.getTypeImpl().getNodeImpl(); DataStore config = weaver.getConfig(); @@ -90,8 +89,8 @@ public static AJoinPoint varDecl(CxxWeaver weaver, String varName, AJoinPoint in * @param joinpoint * @return */ - public static AJoinPoint varDeclNoInit(CxxWeaver weaver, String varName, AType type) { - VarDecl varDecl = weaver.getFactory().varDecl(varName, (Type) type.getNode()); + public static AJoinpoint varDeclNoInit(CxxWeaver weaver, String varName, AType type) { + VarDecl varDecl = weaver.getFactory().varDecl(varName, (Type) type.getNodeImpl()); return CxxJoinpoints.create(varDecl, weaver, AVardecl.class); } @@ -119,7 +118,7 @@ private static Type getVarDeclType(CxxWeaver weaver, Standard standard, Type ret return returnType; } - public static CxxFunction functionVoid(CxxWeaver weaver, String name) { + public static CxxFunction functionVoid(CxxWeaver weaver, String name) { BuiltinType voidType = weaver.getFactory().builtinType(BuiltinKind.Void); FunctionProtoType functionType = weaver.getFactory().functionProtoType(voidType); @@ -130,50 +129,50 @@ public static CxxFunction functionVoid(CxxWeaver weaver, String name) { return CxxJoinpoints.create(functionDecl, weaver, CxxFunction.class); } - public static AStatement stmtLiteral(CxxWeaver weaver, String code) { + public static AStatement stmtLiteral(CxxWeaver weaver, String code) { return CxxJoinpoints.create(weaver.getSnippetParser().parseStmt(code), weaver, AStatement.class); } - public static AType typeLiteral(CxxWeaver weaver, String code) { + public static AType typeLiteral(CxxWeaver weaver, String code) { return CxxJoinpoints.create(weaver.getFactory().literalType(code), weaver, AType.class); } - public static ADecl declLiteral(CxxWeaver weaver, String code) { + public static ADecl declLiteral(CxxWeaver weaver, String code) { return CxxJoinpoints.create(weaver.getFactory().literalDecl(code), weaver, ADecl.class); } - public static AExpression exprLiteral(CxxWeaver weaver, String code) { + public static AExpression exprLiteral(CxxWeaver weaver, String code) { return exprLiteral(weaver, code, CxxJoinpoints.create(weaver.getFactory().nullType(), weaver)); } - public static AExpression exprLiteral(CxxWeaver weaver, String code, AJoinPoint type) { - Type astType = type instanceof AType ? (Type) type.getNode() + public static AExpression exprLiteral(CxxWeaver weaver, String code, AJoinpoint type) { + Type astType = type instanceof AType ? (Type) type.getNodeImpl() : weaver.getFactory().nullType(); return CxxJoinpoints.create(weaver.getFactory().literalExpr(code, astType), weaver, AExpression.class); } - public static AExpression cxxConstructExpr(CxxWeaver weaver, AType type, Object[] constructorArguments) { - return cxxConstructExpr(weaver, type, SpecsCollections.asListT(AJoinPoint.class, constructorArguments)); + public static AExpression cxxConstructExpr(CxxWeaver weaver, AType type, Object[] constructorArguments) { + return cxxConstructExpr(weaver, type, SpecsCollections.asListT(AJoinpoint.class, constructorArguments)); } - public static AExpression cxxConstructExpr(CxxWeaver weaver, AType type, List constructorArguments) { + public static AExpression cxxConstructExpr(CxxWeaver weaver, AType type, List constructorArguments) { List exprArgs = constructorArguments.stream() - .map(arg -> (Expr) arg.getNode()) + .map(arg -> (Expr) arg.getNodeImpl()) .collect(Collectors.toList()); - return CxxJoinpoints.create(weaver.getFactory().cxxConstructExpr((Type) type.getNode(), exprArgs), weaver, AExpression.class); + return CxxJoinpoints.create(weaver.getFactory().cxxConstructExpr((Type) type.getNodeImpl(), exprArgs), weaver, AExpression.class); } - public static ACall callFromFunction(CxxWeaver weaver, AFunction function, Object[] args) { - return callFromFunction(weaver, function, SpecsCollections.asListT(AJoinPoint.class, args)); + public static ACall callFromFunction(CxxWeaver weaver, AFunction function, Object[] args) { + return callFromFunction(weaver, function, SpecsCollections.asListT(AJoinpoint.class, args)); } - public static ACall callFromFunction(CxxWeaver weaver, AFunction function, List args) { - var functionDecl = (FunctionDecl) function.getNode(); + public static ACall callFromFunction(CxxWeaver weaver, AFunction function, List args) { + var functionDecl = (FunctionDecl) function.getNodeImpl(); List exprArgs = args.stream() - .map(arg -> (Expr) arg.getNode()) + .map(arg -> (Expr) arg.getNodeImpl()) .collect(Collectors.toList()); var call = weaver.getFactory().callExpr(functionDecl, exprArgs); @@ -181,24 +180,24 @@ public static ACall callFromFunction(CxxWeaver weaver, AFunction function, List< return CxxJoinpoints.create(call, weaver, ACall.class); } - public static ACall call(CxxWeaver weaver, String functionName, AType typeJp, Object[] args) { - return call(weaver, functionName, typeJp, SpecsCollections.asListT(AJoinPoint.class, args)); + public static ACall call(CxxWeaver weaver, String functionName, AType typeJp, Object[] args) { + return call(weaver, functionName, typeJp, SpecsCollections.asListT(AJoinpoint.class, args)); } - public static ACall call(CxxWeaver weaver, String functionName, AType typeJp, List args) { + public static ACall call(CxxWeaver weaver, String functionName, AType typeJp, List args) { - Type returnType = (Type) typeJp.getNode(); + Type returnType = (Type) typeJp.getNodeImpl(); DeclRefExpr declRef = weaver.getFactory().declRefExpr(functionName, returnType); List argTypes = args.stream() - .map(arg -> ((Typable) arg.getNode()).getType()) + .map(arg -> ((Typable) arg.getNodeImpl()).getType()) .collect(Collectors.toList()); FunctionProtoType type = weaver.getFactory().functionProtoType(returnType, argTypes); List exprArgs = args.stream() - .map(arg -> (Expr) arg.getNode()) + .map(arg -> (Expr) arg.getNodeImpl()) .collect(Collectors.toList()); CallExpr call = weaver.getFactory().callExpr(declRef, type, exprArgs); @@ -213,7 +212,7 @@ public static ACall call(CxxWeaver weaver, String functionName, AType typeJp, Li * @param joinpoint * @return */ - public static AFile file(CxxWeaver weaver, File file, String relativePath) { + public static AFile file(CxxWeaver weaver, File file, String relativePath) { // Test if path is absolute if (relativePath != null && new File(relativePath).isAbsolute()) { @@ -233,7 +232,7 @@ public static AFile file(CxxWeaver weaver, File file, String relativePath) { // If file already exists, insert the code of the file literaly if (file.isFile()) { - fileJp.getNode().setOptional(TranslationUnit.LITERAL_SOURCE, SpecsIo.read(file)); + fileJp.getNodeImpl().setOptional(TranslationUnit.LITERAL_SOURCE, SpecsIo.read(file)); } return fileJp; @@ -247,11 +246,11 @@ public static AFile file(CxxWeaver weaver, File file, String relativePath) { * @param relativePath * @return */ - public static AFile file(CxxWeaver weaver, String filename, String contents, String relativePath) { + public static AFile file(CxxWeaver weaver, String filename, String contents, String relativePath) { var fileJp = file(weaver, new File(filename), relativePath); // Add contents - fileJp.getNode().setOptional(TranslationUnit.LITERAL_SOURCE, contents); + fileJp.getNodeImpl().setOptional(TranslationUnit.LITERAL_SOURCE, contents); return fileJp; } @@ -263,23 +262,23 @@ public static AFile file(CxxWeaver weaver, String filename, String contents, Str * @param relativePath * @return */ - public static AFile file(CxxWeaver weaver, String filename, String relativePath) { + public static AFile file(CxxWeaver weaver, String filename, String relativePath) { return file(weaver, new File(filename), relativePath); } - public static AJoinPoint externC(CxxWeaver weaver, AJoinPoint jpDecl) { + public static AJoinpoint externC(CxxWeaver weaver, AJoinpoint jpDecl) { // Allowed classes for now: CxxFunction // TODO: This might be expanded in the future boolean isFunction = jpDecl instanceof CxxFunction; if (!isFunction) { ClavaLog.warning( - "Constructor 'externC' does not support joinpoint of type '" + jpDecl.getJoinPointType() + "'"); + "Constructor 'externC' does not support joinpoint of type '" + jpDecl.getJoinPointTypeImpl() + "'"); return null; } // Check that node does not already has a parent LinkageSpecDecl - ClavaNode decl = jpDecl.getNode(); + ClavaNode decl = jpDecl.getNodeImpl(); if (decl.getParent() instanceof LinkageSpecDecl) { ClavaLog.warning("Given joinpoint already is marked as 'extern \"C\"'"); return null; @@ -291,12 +290,12 @@ public static AJoinPoint externC(CxxWeaver weaver, AJoinPoint jpDecl) { return CxxJoinpoints.create(linkage, weaver); } - public static ACxxWeaverJoinPoint constArrayType(CxxWeaver weaver, + public static AJoinpoint constArrayType(CxxWeaver weaver, String typeCode, String standard, List dims) { return constArrayType(weaver, weaver.getFactory().literalType(typeCode), standard, dims); } - public static ACxxWeaverJoinPoint constArrayType(CxxWeaver weaver, + public static AJoinpoint constArrayType(CxxWeaver weaver, String typeCode, String standard, Object[] dims) { return constArrayType(weaver, typeCode, standard, SpecsCollections.asListT(Integer.class, dims)); } @@ -309,7 +308,7 @@ public static ACxxWeaverJoinPoint constArrayType(CxxWeaver weaver, * @param dims * @return */ - public static ACxxWeaverJoinPoint constArrayType(CxxWeaver weaver, + public static AJoinpoint constArrayType(CxxWeaver weaver, Type outType, String standardString, List dims) { Objects.requireNonNull(dims); @@ -326,45 +325,45 @@ public static ACxxWeaverJoinPoint constArrayType(CxxWeaver weaver, return CxxJoinpoints.create(outType, weaver); } - public static ACxxWeaverJoinPoint constArrayType(CxxWeaver weaver, + public static AJoinpoint constArrayType(CxxWeaver weaver, Type outType, String standardString, Object[] dims) { return constArrayType(weaver, outType, standardString, SpecsCollections.asListT(Integer.class, dims)); } - public static AVariableArrayType variableArrayType(CxxWeaver weaver, AType elementType, AExpression sizeExpr) { - Type variableArrayType = weaver.getFactory().variableArrayType((Type) elementType.getNode(), - (Expr) sizeExpr.getNode()); + public static AVariableArrayType variableArrayType(CxxWeaver weaver, AType elementType, AExpression sizeExpr) { + Type variableArrayType = weaver.getFactory().variableArrayType((Type) elementType.getNodeImpl(), + (Expr) sizeExpr.getNodeImpl()); return CxxJoinpoints.create(variableArrayType, weaver, AVariableArrayType.class); } - public static AIncompleteArrayType incompleteArrayType(CxxWeaver weaver, AType elementType) { - Type incompleteArrayType = weaver.getFactory().incompleteArrayType(((Type) elementType.getNode())); + public static AIncompleteArrayType incompleteArrayType(CxxWeaver weaver, AType elementType) { + Type incompleteArrayType = weaver.getFactory().incompleteArrayType(((Type) elementType.getNodeImpl())); return CxxJoinpoints.create(incompleteArrayType, weaver, AIncompleteArrayType.class); } - public static AJoinPoint omp(CxxWeaver weaver, String directiveName) { + public static AJoinpoint omp(CxxWeaver weaver, String directiveName) { // Get directive OmpDirectiveKind kind = OmpDirectiveKind.getHelper().fromValue(directiveName); return CxxJoinpoints.create(OmpParser.newOmpPragma(kind, weaver.getContex()), weaver); } - public static AStatement caseStmt(CxxWeaver weaver, AExpression value) { + public static AStatement caseStmt(CxxWeaver weaver, AExpression value) { - CaseStmt caseStmt = weaver.getFactory().caseStmt((Expr) value.getNode()); + CaseStmt caseStmt = weaver.getFactory().caseStmt((Expr) value.getNodeImpl()); return CxxJoinpoints.create(caseStmt, weaver, AStatement.class); } - public static AStatement defaultStmt(CxxWeaver weaver) { + public static AStatement defaultStmt(CxxWeaver weaver) { var defaultStmt = weaver.getFactory().defaultStmt(); return CxxJoinpoints.create(defaultStmt, weaver, AStatement.class); } - public static AStatement breakStmt(CxxWeaver weaver) { + public static AStatement breakStmt(CxxWeaver weaver) { var breakStmt = weaver.getFactory().breakStmt(); return CxxJoinpoints.create(breakStmt, weaver, AStatement.class); } @@ -374,29 +373,29 @@ public static AStatement breakStmt(CxxWeaver weaver) { * @param expr * @return a list with a case statement and a break statement */ - public static List caseFromExpr(CxxWeaver weaver, AExpression value, AExpression expr) { + public static List> caseFromExpr(CxxWeaver weaver, AExpression value, AExpression expr) { // Create compound stmt - ExprStmt exprStmt = weaver.getFactory().exprStmt((Expr) expr.getNode()); + ExprStmt exprStmt = weaver.getFactory().exprStmt((Expr) expr.getNodeImpl()); BreakStmt breakStmt = weaver.getFactory().breakStmt(); var breakJp = CxxJoinpoints.create(breakStmt, weaver, AStatement.class); CompoundStmt compoundStmt = weaver.getFactory().compoundStmt(exprStmt); compoundStmt.setNaked(true); - AStatement caseStmt = caseStmt(weaver, value); + AStatement caseStmt = caseStmt(weaver, value); var compoundJp = CxxJoinpoints.create(compoundStmt, weaver, AStatement.class); return Arrays.asList(caseStmt, compoundJp, breakJp); } - public static AStatement switchStmt(CxxWeaver weaver, AExpression condition, AStatement body) { - Stmt switchStmt = weaver.getFactory().switchStmt((Expr) condition.getNode(), (Stmt) body.getNode()); + public static AStatement switchStmt(CxxWeaver weaver, AExpression condition, AStatement body) { + Stmt switchStmt = weaver.getFactory().switchStmt((Expr) condition.getNodeImpl(), (Stmt) body.getNodeImpl()); return CxxJoinpoints.create(switchStmt, weaver, AStatement.class); } - public static AStatement switchStmt(CxxWeaver weaver, AExpression condition, Object[] casesArray) { + public static AStatement switchStmt(CxxWeaver weaver, AExpression condition, Object[] casesArray) { var cases = SpecsCollections.cast(casesArray, AExpression.class); if (cases.length % 2 != 0) { @@ -409,88 +408,88 @@ public static AStatement switchStmt(CxxWeaver weaver, AExpression condition, Obj for (int i = 0; i < cases.length; i += 2) { statements.addAll(caseFromExpr(weaver, cases[i], cases[i + 1]).stream() - .map(aStmt -> (Stmt) aStmt.getNode()) + .map(aStmt -> (Stmt) aStmt.getNodeImpl()) .collect(Collectors.toList())); } CompoundStmt body = weaver.getFactory().compoundStmt(statements); - Stmt switchStmt = weaver.getFactory().switchStmt((Expr) condition.getNode(), body); + Stmt switchStmt = weaver.getFactory().switchStmt((Expr) condition.getNodeImpl(), body); return CxxJoinpoints.create(switchStmt, weaver, AStatement.class); } ////// Methods that only use ClavaFactory - public static ACxxWeaverJoinPoint builtinType(CxxWeaver weaver, String typeCode) { + public static AJoinpoint builtinType(CxxWeaver weaver, String typeCode) { BuiltinType type = weaver.getFactory().builtinType(typeCode); return CxxJoinpoints.create(type, weaver); } - public static ACxxWeaverJoinPoint pointerTypeFromBuiltin(CxxWeaver weaver, String typeCode) { + public static AJoinpoint pointerTypeFromBuiltin(CxxWeaver weaver, String typeCode) { BuiltinType pointeeType = weaver.getFactory().builtinType(typeCode); PointerType pointerType = weaver.getFactory().pointerType(pointeeType); - ACxxWeaverJoinPoint jp = CxxJoinpoints.create(pointerType, weaver); + AJoinpoint jp = CxxJoinpoints.create(pointerType, weaver); return jp; } - public static ACxxWeaverJoinPoint pointerType(CxxWeaver weaver, AType pointeeType) { - PointerType pointerType = weaver.getFactory().pointerType((Type) pointeeType.getNode()); + public static AJoinpoint pointerType(CxxWeaver weaver, AType pointeeType) { + PointerType pointerType = weaver.getFactory().pointerType((Type) pointeeType.getNodeImpl()); - ACxxWeaverJoinPoint jp = CxxJoinpoints.create(pointerType, weaver); + AJoinpoint jp = CxxJoinpoints.create(pointerType, weaver); return jp; } - public static AExpression doubleLiteral(CxxWeaver weaver, String floating) { + public static AExpression doubleLiteral(CxxWeaver weaver, String floating) { return doubleLiteral(weaver, Double.parseDouble(floating)); } - public static AExpression doubleLiteral(CxxWeaver weaver, double floating) { + public static AExpression doubleLiteral(CxxWeaver weaver, double floating) { FloatingLiteral floatingLiteral = weaver.getFactory() .floatingLiteral(FloatKind.DOUBLE, floating); return CxxJoinpoints.create(floatingLiteral, weaver, AExpression.class); } - public static ACxxWeaverJoinPoint longType(CxxWeaver weaver) { + public static AJoinpoint longType(CxxWeaver weaver) { BuiltinType type = weaver.getFactory().builtinType(BuiltinKind.Long); return CxxJoinpoints.create(type, weaver); } - public static AExpression integerLiteral(CxxWeaver weaver, String integer) { + public static AExpression integerLiteral(CxxWeaver weaver, String integer) { return integerLiteral(weaver, Integer.parseInt(integer)); } - public static AExpression integerLiteral(CxxWeaver weaver, int integer) { + public static AExpression integerLiteral(CxxWeaver weaver, int integer) { IntegerLiteral intLiteral = weaver.getFactory().integerLiteral(integer); return CxxJoinpoints.create(intLiteral, weaver, AExpression.class); } - public static AScope scope(CxxWeaver weaver) { + public static AScope scope(CxxWeaver weaver) { return scope(weaver, Collections.emptyList()); } - public static AScope scope(CxxWeaver weaver, Object[] statements) { + public static AScope scope(CxxWeaver weaver, Object[] statements) { return scope(weaver, SpecsCollections.asListT(AStatement.class, statements)); } - public static AScope scope(CxxWeaver weaver, List statements) { - List stmtNodes = SpecsCollections.map(statements, stmt -> (Stmt) stmt.getNode()); + public static AScope scope(CxxWeaver weaver, List statements) { + List stmtNodes = SpecsCollections.map(statements, stmt -> (Stmt) stmt.getNodeImpl()); return CxxJoinpoints.create(weaver.getFactory().compoundStmt(stmtNodes), weaver, AScope.class); } - public static AVarref varref(CxxWeaver weaver, String declName, AType type) { - Type typeNode = (Type) type.getNode(); + public static AVarref varref(CxxWeaver weaver, String declName, AType type) { + Type typeNode = (Type) type.getNodeImpl(); return CxxJoinpoints.create(weaver.getFactory().declRefExpr(declName, typeNode), weaver, AVarref.class); } - public static AVarref varref(CxxWeaver weaver, ANamedDecl namedDecl) { - NamedDecl decl = (NamedDecl) namedDecl.getNode(); + public static AVarref varref(CxxWeaver weaver, ANamedDecl namedDecl) { + NamedDecl decl = (NamedDecl) namedDecl.getNodeImpl(); if (!(decl instanceof ValueDecl)) { ClavaLog.info( @@ -501,25 +500,25 @@ public static AVarref varref(CxxWeaver weaver, ANamedDecl namedDecl) { return CxxJoinpoints.create(weaver.getFactory().declRefExpr((ValueDecl) decl), weaver, AVarref.class); } - public static AStatement returnStmt(CxxWeaver weaver, AExpression expr) { - return CxxJoinpoints.create(weaver.getFactory().returnStmt((Expr) expr.getNode()), weaver, AStatement.class); + public static AStatement returnStmt(CxxWeaver weaver, AExpression expr) { + return CxxJoinpoints.create(weaver.getFactory().returnStmt((Expr) expr.getNodeImpl()), weaver, AStatement.class); } - public static AStatement returnStmt(CxxWeaver weaver) { + public static AStatement returnStmt(CxxWeaver weaver) { return CxxJoinpoints.create(weaver.getFactory().returnStmt(), weaver, AStatement.class); } - public static AFunctionType functionType(CxxWeaver weaver, AType returnTypeJp, Object[] argTypesJps) { + public static AFunctionType functionType(CxxWeaver weaver, AType returnTypeJp, Object[] argTypesJps) { return functionType(weaver, returnTypeJp, SpecsCollections.asListT(AType.class, argTypesJps)); } - public static AFunctionType functionType(CxxWeaver weaver, AType returnTypeJp, List argTypesJps) { + public static AFunctionType functionType(CxxWeaver weaver, AType returnTypeJp, List argTypesJps) { - Type returnType = (Type) returnTypeJp.getNode(); + Type returnType = (Type) returnTypeJp.getNodeImpl(); List argTypes = argTypesJps.stream() - .map(arg -> ((Type) arg.getNode())) + .map(arg -> ((Type) arg.getNodeImpl())) .collect(Collectors.toList()); FunctionProtoType type = weaver.getFactory().functionProtoType(returnType, argTypes); @@ -527,22 +526,22 @@ public static AFunctionType functionType(CxxWeaver weaver, AType returnTypeJp, L return CxxJoinpoints.create(type, weaver, AFunctionType.class); } - public static AFunction functionDeclFromType(CxxWeaver weaver, String functionName, AFunctionType functionTypeJp) { - FunctionType functionType = (FunctionType) functionTypeJp.getNode(); + public static AFunction functionDeclFromType(CxxWeaver weaver, String functionName, AFunctionType functionTypeJp) { + FunctionType functionType = (FunctionType) functionTypeJp.getNodeImpl(); return CxxJoinpoints.create(weaver.getFactory().functionDecl(functionName, functionType), weaver, AFunction.class); } - public static AFunction functionDecl(CxxWeaver weaver, String functionName, AType returnTypeJp, List namedDeclJps) { + public static AFunction functionDecl(CxxWeaver weaver, String functionName, AType returnTypeJp, List namedDeclJps) { - Type returnType = (Type) returnTypeJp.getNode(); + Type returnType = (Type) returnTypeJp.getNodeImpl(); // Get the arg types and create the parameters List argTypes = new ArrayList<>(namedDeclJps.size()); List params = new ArrayList<>(); - for (AJoinPoint namedDeclJp : namedDeclJps) { - ClavaNode node = namedDeclJp.getNode(); + for (AJoinpoint namedDeclJp : namedDeclJps) { + ClavaNode node = namedDeclJp.getNodeImpl(); if (!(node instanceof ValueDecl)) { ClavaLog.info("AstFactory.functionDecl: decl '" + node.getClass() + "' is not compatible as parameter of function"); @@ -565,13 +564,13 @@ public static AFunction functionDecl(CxxWeaver weaver, String functionName, ATyp return CxxJoinpoints.create(functionDecl, weaver, AFunction.class); } - public static AFunction functionDecl(CxxWeaver weaver, String functionName, AType returnTypeJp, Object... namedDeclJps) { - return functionDecl(weaver, functionName, returnTypeJp, SpecsCollections.asListT(AJoinPoint.class, namedDeclJps)); + public static AFunction functionDecl(CxxWeaver weaver, String functionName, AType returnTypeJp, Object... namedDeclJps) { + return functionDecl(weaver, functionName, returnTypeJp, SpecsCollections.asListT(AJoinpoint.class, namedDeclJps)); } - public static ABinaryOp assignment(CxxWeaver weaver, AExpression leftHand, AExpression rightHand) { - Expr lhs = (Expr) leftHand.getNode(); - Expr rhs = (Expr) rightHand.getNode(); + public static ABinaryOp assignment(CxxWeaver weaver, AExpression leftHand, AExpression rightHand) { + Expr lhs = (Expr) leftHand.getNodeImpl(); + Expr rhs = (Expr) rightHand.getNodeImpl(); BinaryOperator assign = weaver.getFactory().binaryOperator(BinaryOperatorKind.Assign, lhs.getType(), lhs, rhs); @@ -579,86 +578,86 @@ public static ABinaryOp assignment(CxxWeaver weaver, AExpression leftHand, AExpr return CxxJoinpoints.create(assign, weaver, ABinaryOp.class); } - public static AIf ifStmt(CxxWeaver weaver, AExpression condition, AStatement thenBody, AStatement elseBody) { - var thenNode = thenBody != null ? ClavaNodes.toCompoundStmt((Stmt) thenBody.getNode()) : null; - var elseNode = elseBody != null ? ClavaNodes.toCompoundStmt((Stmt) elseBody.getNode()) : null; + public static AIf ifStmt(CxxWeaver weaver, AExpression condition, AStatement thenBody, AStatement elseBody) { + var thenNode = thenBody != null ? ClavaNodes.toCompoundStmt((Stmt) thenBody.getNodeImpl()) : null; + var elseNode = elseBody != null ? ClavaNodes.toCompoundStmt((Stmt) elseBody.getNodeImpl()) : null; - IfStmt ifStmt = weaver.getFactory().ifStmt((Expr) condition.getNode(), thenNode, elseNode); + IfStmt ifStmt = weaver.getFactory().ifStmt((Expr) condition.getNodeImpl(), thenNode, elseNode); return CxxJoinpoints.create(ifStmt, weaver, AIf.class); } - public static ABinaryOp binaryOp(CxxWeaver weaver, String op, AExpression left, AExpression right, AType type) { + public static ABinaryOp binaryOp(CxxWeaver weaver, String op, AExpression left, AExpression right, AType type) { BinaryOperatorKind opKind = BinaryOperator.getOpByNameOrSymbol(op); - BinaryOperator opNode = weaver.getFactory().binaryOperator(opKind, (Type) type.getNode(), - (Expr) left.getNode(), (Expr) right.getNode()); + BinaryOperator opNode = weaver.getFactory().binaryOperator(opKind, (Type) type.getNodeImpl(), + (Expr) left.getNodeImpl(), (Expr) right.getNodeImpl()); return CxxJoinpoints.create(opNode, weaver, ABinaryOp.class); } - public static ABinaryOp compoundAssignment(CxxWeaver weaver, String op, AExpression lhs, AExpression rhs) { + public static ABinaryOp compoundAssignment(CxxWeaver weaver, String op, AExpression lhs, AExpression rhs) { var opKind = BinaryOperator.getOpByNameOrSymbol(op); - var type = ((Expr) lhs.getNode()).getType(); + var type = ((Expr) lhs.getNodeImpl()).getType(); - var opNode = weaver.getFactory().compoundAssignOperator(opKind, type, (Expr) lhs.getNode(), - (Expr) rhs.getNode()); + var opNode = weaver.getFactory().compoundAssignOperator(opKind, type, (Expr) lhs.getNodeImpl(), + (Expr) rhs.getNodeImpl()); return CxxJoinpoints.create(opNode, weaver, ABinaryOp.class); } - public static AUnaryOp unaryOp(CxxWeaver weaver, String op, AExpression expr, AType type) { + public static AUnaryOp unaryOp(CxxWeaver weaver, String op, AExpression expr, AType type) { UnaryOperatorKind opKind = UnaryOperator.getOpByNameOrSymbol(op); // If type is null, try to infer type from operator - var typeNode = type != null ? (Type) type.getNode() - : Types.inferUnaryType(opKind, (Type) expr.getTypeImpl().getNode(), weaver.getFactory()); + var typeNode = type != null ? (Type) type.getNodeImpl() + : Types.inferUnaryType(opKind, (Type) expr.getTypeImpl().getNodeImpl(), weaver.getFactory()); UnaryOperator opNode = weaver.getFactory().unaryOperator(opKind, typeNode, - (Expr) expr.getNode()); + (Expr) expr.getNodeImpl()); return CxxJoinpoints.create(opNode, weaver, AUnaryOp.class); } - public static ATernaryOp ternaryOp(CxxWeaver weaver, AExpression cond, AExpression trueExpr, AExpression falseExpr, AType type) { + public static ATernaryOp ternaryOp(CxxWeaver weaver, AExpression cond, AExpression trueExpr, AExpression falseExpr, AType type) { ConditionalOperator opNode = weaver.getFactory().conditionalOperator( - (Type) type.getNode(), - (Expr) cond.getNode(), - (Expr) trueExpr.getNode(), - (Expr) falseExpr.getNode()); + (Type) type.getNodeImpl(), + (Expr) cond.getNodeImpl(), + (Expr) trueExpr.getNodeImpl(), + (Expr) falseExpr.getNodeImpl()); return CxxJoinpoints.create(opNode, weaver, ATernaryOp.class); } - public static AExpression parenthesis(CxxWeaver weaver, AExpression expression) { - ParenExpr parenExpr = weaver.getFactory().parenExpr((Expr) expression.getNode()); + public static AExpression parenthesis(CxxWeaver weaver, AExpression expression) { + ParenExpr parenExpr = weaver.getFactory().parenExpr((Expr) expression.getNodeImpl()); return CxxJoinpoints.create(parenExpr, weaver, AExpression.class); } - public static AArrayAccess arrayAccess(CxxWeaver weaver, AExpression base, List subscripts) { + public static AArrayAccess arrayAccess(CxxWeaver weaver, AExpression base, List subscripts) { var subscriptsExpr = subscripts.stream() - .map(arg -> ((Expr) arg.getNode())) + .map(arg -> ((Expr) arg.getNodeImpl())) .collect(Collectors.toList()); - var arraySubscriptExpr = weaver.getFactory().arraySubscriptExpr((Expr) base.getNode(), subscriptsExpr); + var arraySubscriptExpr = weaver.getFactory().arraySubscriptExpr((Expr) base.getNodeImpl(), subscriptsExpr); return CxxJoinpoints.create(arraySubscriptExpr, weaver, AArrayAccess.class); } - public static AArrayAccess arrayAccess(CxxWeaver weaver, AExpression base, Object[] subscripts) { + public static AArrayAccess arrayAccess(CxxWeaver weaver, AExpression base, Object[] subscripts) { return arrayAccess(weaver, base, SpecsCollections.asListT(AExpression.class, subscripts)); } - public static AInitList initList(CxxWeaver weaver, List values) { + public static AInitList initList(CxxWeaver weaver, List values) { var valuesExpr = values.stream() - .map(arg -> ((Expr) arg.getNode())) + .map(arg -> ((Expr) arg.getNodeImpl())) .collect(Collectors.toList()); var initList = weaver.getFactory().initListExpr((valuesExpr)); return CxxJoinpoints.create(initList, weaver, AInitList.class); } - public static AInitList initList(CxxWeaver weaver, Object[] values) { + public static AInitList initList(CxxWeaver weaver, Object[] values) { return initList(weaver, SpecsCollections.asListT(AExpression.class, values)); } @@ -669,25 +668,25 @@ public static AInitList initList(CxxWeaver weaver, Object[] values) { * @param joinpoint * @return */ - public static AType typedefType(CxxWeaver weaver, ATypedefDecl typedefDecl) { - var typedefType = weaver.getFactory().typedefType((TypedefDecl) typedefDecl.getNode()); + public static AType typedefType(CxxWeaver weaver, ATypedefDecl typedefDecl) { + var typedefType = weaver.getFactory().typedefType((TypedefDecl) typedefDecl.getNodeImpl()); return CxxJoinpoints.create(typedefType, weaver, AType.class); } - public static ATypedefDecl typedefDecl(CxxWeaver weaver, AType underlyingType, String identifier) { - var typedefDecl = weaver.getFactory().typedefDecl((Type) underlyingType.getNode(), identifier); + public static ATypedefDecl typedefDecl(CxxWeaver weaver, AType underlyingType, String identifier) { + var typedefDecl = weaver.getFactory().typedefDecl((Type) underlyingType.getNodeImpl(), identifier); return CxxJoinpoints.create(typedefDecl, weaver, ATypedefDecl.class); } - public static AElaboratedType structType(CxxWeaver weaver, AStruct struct) { - var namedType = (Type) struct.getTypeImpl().getNode(); - var elaboratedType = weaver.getFactory().elaboratedType(ElaboratedTypeKeyword.STRUCT, namedType); + public static AElaboratedType structType(CxxWeaver weaver, AStruct struct) { + var namedType = (Type) struct.getTypeImpl().getNodeImpl(); + var elaboratedType = weaver.getFactory().elaboratedType(ElaboratedTypeKeyword.Struct, namedType); return CxxJoinpoints.create(elaboratedType, weaver, AElaboratedType.class); } - public static ACast cStyleCast(CxxWeaver weaver, AType type, AExpression expr) { - var cast = weaver.getFactory().cStyleCastExpr((Type) type.getNode(), (Expr) expr.getNode()); + public static ACast cStyleCast(CxxWeaver weaver, AType type, AExpression expr) { + var cast = weaver.getFactory().cStyleCastExpr((Type) type.getNodeImpl(), (Expr) expr.getNodeImpl()); return CxxJoinpoints.create(cast, weaver, ACast.class); } @@ -699,15 +698,15 @@ public static ACast cStyleCast(CxxWeaver weaver, AType type, AExpression expr) { * @param joinpoint * @return */ - public static AClass classDecl(CxxWeaver weaver, String className, List fields) { - var fieldsNodes = fields.stream().map(field -> (FieldDecl) field.getNode()) + public static AClass classDecl(CxxWeaver weaver, String className, List fields) { + var fieldsNodes = fields.stream().map(field -> (FieldDecl) field.getNodeImpl()) .collect(Collectors.toList()); var classDecl = weaver.getFactory().cxxRecordDecl(className, fieldsNodes); return CxxJoinpoints.create(classDecl, weaver, AClass.class); } - public static AClass classDecl(CxxWeaver weaver, String className, Object... fields) { + public static AClass classDecl(CxxWeaver weaver, String className, Object... fields) { return classDecl(weaver, className, SpecsCollections.asListT(AField.class, fields)); } @@ -718,8 +717,8 @@ public static AClass classDecl(CxxWeaver weaver, String className, Object... fie * @param fieldType * @return */ - public static AField field(CxxWeaver weaver, String fieldName, AType fieldType) { - var fieldDecl = weaver.getFactory().fieldDecl(fieldName, (Type) fieldType.getNode()); + public static AField field(CxxWeaver weaver, String fieldName, AType fieldType) { + var fieldDecl = weaver.getFactory().fieldDecl(fieldName, (Type) fieldType.getNodeImpl()); return CxxJoinpoints.create(fieldDecl, weaver, AField.class); } @@ -730,21 +729,21 @@ public static AField field(CxxWeaver weaver, String fieldName, AType fieldType) * @param fieldType * @return */ - public static AAccessSpecifier accessSpecifier(CxxWeaver weaver, String accessSpecifierString) { + public static AAccessSpecifier accessSpecifier(CxxWeaver weaver, String accessSpecifierString) { var accessSpecifier = SpecsEnums.fromName(AccessSpecifier.class, accessSpecifierString.toUpperCase()); var accessSpecifierDecl = weaver.getFactory().accessSpecDecl(accessSpecifier); return CxxJoinpoints.create(accessSpecifierDecl, weaver, AAccessSpecifier.class); } - public static ALoop forStmt(CxxWeaver weaver, - AStatement init, AStatement condition, AStatement inc, AStatement body) { + public static ALoop forStmt(CxxWeaver weaver, + AStatement init, AStatement condition, AStatement inc, AStatement body) { // If null, create NullStmt - var initStmt = init != null ? (Stmt) init.getNode() : weaver.getFactory().nullStmt(); - var condStmt = condition != null ? (Stmt) condition.getNode() : weaver.getFactory().nullStmt(); - var incStmt = inc != null ? (Stmt) inc.getNode() : weaver.getFactory().nullStmt(); - var bodyStmt = body != null ? (Stmt) body.getNode() : weaver.getFactory().nullStmt(); + var initStmt = init != null ? (Stmt) init.getNodeImpl() : weaver.getFactory().nullStmt(); + var condStmt = condition != null ? (Stmt) condition.getNodeImpl() : weaver.getFactory().nullStmt(); + var incStmt = inc != null ? (Stmt) inc.getNodeImpl() : weaver.getFactory().nullStmt(); + var bodyStmt = body != null ? (Stmt) body.getNodeImpl() : weaver.getFactory().nullStmt(); // If body is not a CompoundStmt, make it @@ -755,9 +754,9 @@ public static ALoop forStmt(CxxWeaver weaver, return CxxJoinpoints.create(forStmt, weaver, ALoop.class); } - public static ALoop whileStmt(CxxWeaver weaver, AStatement condition, AStatement body) { - var condStmt = condition != null ? (Stmt) condition.getNode() : weaver.getFactory().nullStmt(); - var bodyStmt = body != null ? (Stmt) body.getNode() : weaver.getFactory().nullStmt(); + public static ALoop whileStmt(CxxWeaver weaver, AStatement condition, AStatement body) { + var condStmt = condition != null ? (Stmt) condition.getNodeImpl() : weaver.getFactory().nullStmt(); + var bodyStmt = body != null ? (Stmt) body.getNodeImpl() : weaver.getFactory().nullStmt(); var compoundStmt = ClavaNodes.toCompoundStmt(bodyStmt); @@ -772,12 +771,12 @@ public static ALoop whileStmt(CxxWeaver weaver, AStatement condition, AStatement * @param type * @return */ - public static AParam param(CxxWeaver weaver, String name, AType type) { - var param = weaver.getFactory().parmVarDecl(name, (Type) type.getNode()); + public static AParam param(CxxWeaver weaver, String name, AType type) { + var param = weaver.getFactory().parmVarDecl(name, (Type) type.getNodeImpl()); return CxxJoinpoints.create(param, weaver, AParam.class); } - public static AComment comment(CxxWeaver weaver, String text) { + public static AComment comment(CxxWeaver weaver, String text) { // TODO: Detect C standard, to detect if inline comments are supported? @@ -789,8 +788,8 @@ public static AComment comment(CxxWeaver weaver, String text) { return CxxJoinpoints.create(comment, weaver, AComment.class); } - public static AExprStmt exprStmt(CxxWeaver weaver, AExpression expr) { - var exprStmt = weaver.getFactory().exprStmt((Expr) expr.getNode()); + public static AExprStmt exprStmt(CxxWeaver weaver, AExpression expr) { + var exprStmt = weaver.getFactory().exprStmt((Expr) expr.getNodeImpl()); return CxxJoinpoints.create(exprStmt, weaver, AExprStmt.class); } @@ -801,15 +800,15 @@ public static AExprStmt exprStmt(CxxWeaver weaver, AExpression expr) { * @param joinpoint * @return */ - public static ADeclStmt declStmt(CxxWeaver weaver, List decls) { - var declNodes = decls.stream().map(decl -> (Decl) decl.getNode()) + public static ADeclStmt declStmt(CxxWeaver weaver, List decls) { + var declNodes = decls.stream().map(decl -> (Decl) decl.getNodeImpl()) .collect(Collectors.toList()); var declStmt = weaver.getFactory().declStmt(declNodes); return CxxJoinpoints.create(declStmt, weaver, ADeclStmt.class); } - public static ADeclStmt declStmt(CxxWeaver weaver, Object... decls) { + public static ADeclStmt declStmt(CxxWeaver weaver, Object... decls) { return declStmt(weaver, SpecsCollections.asListT(ADecl.class, decls)); } @@ -820,7 +819,7 @@ public static ADeclStmt declStmt(CxxWeaver weaver, Object... decls) { * @param name Name of the label * @return The created label declaration */ - public static ALabelDecl labelDecl(CxxWeaver weaver, String name) { + public static ALabelDecl labelDecl(CxxWeaver weaver, String name) { var decl = weaver.getFactory().labelDecl(name); return CxxJoinpoints.create(decl, weaver, ALabelDecl.class); } @@ -831,8 +830,8 @@ public static ALabelDecl labelDecl(CxxWeaver weaver, String name) { * @param decl The declaration for this statement * @return The label statement to be used in the code. */ - public static ALabelStmt labelStmt(CxxWeaver weaver, ALabelDecl decl) { - var stmt = decl.getFactory().labelStmt((LabelDecl) decl.getNode()); + public static ALabelStmt labelStmt(CxxWeaver weaver, ALabelDecl decl) { + var stmt = decl.getFactory().labelStmt((LabelDecl) decl.getNodeImpl()); return CxxJoinpoints.create(stmt, weaver, ALabelStmt.class); } @@ -842,7 +841,7 @@ public static ALabelStmt labelStmt(CxxWeaver weaver, ALabelDecl decl) { * @param name Name of the label * @return The created */ - public static ALabelStmt labelStmt(CxxWeaver weaver, String name) { + public static ALabelStmt labelStmt(CxxWeaver weaver, String name) { return labelStmt(weaver, labelDecl(weaver, name)); } @@ -852,41 +851,41 @@ public static ALabelStmt labelStmt(CxxWeaver weaver, String name) { * @param label The declaration of the label to jump to * @return The created goto statement */ - public static AGotoStmt gotoStmt(CxxWeaver weaver, ALabelDecl label) { - var stmt = label.getFactory().gotoStmt((LabelDecl) label.getNode()); + public static AGotoStmt gotoStmt(CxxWeaver weaver, ALabelDecl label) { + var stmt = label.getFactory().gotoStmt((LabelDecl) label.getNodeImpl()); return CxxJoinpoints.create(stmt, weaver, AGotoStmt.class); } - public static AEmptyStmt emptyStmt(CxxWeaver weaver) { + public static AEmptyStmt emptyStmt(CxxWeaver weaver) { var stmt = weaver.getFactory().emptyStmt(); return CxxJoinpoints.create(stmt, weaver, AEmptyStmt.class); } - public static AProgram program(CxxWeaver weaver) { + public static AProgram program(CxxWeaver weaver) { var app = weaver.getFactory().app(Collections.emptyList()); return CxxJoinpoints.create(app, weaver, AProgram.class); } - public static AMemberAccess memberAccess(CxxWeaver weaver, AExpression baseExpr, AField field) { - var fieldNode = (FieldDecl) field.getNode(); + public static AMemberAccess memberAccess(CxxWeaver weaver, AExpression baseExpr, AField field) { + var fieldNode = (FieldDecl) field.getNodeImpl(); - var memberAccess = weaver.getFactory().memberExpr(fieldNode.get(FieldDecl.DECL_NAME), fieldNode.get(FieldDecl.TYPE), (Expr) baseExpr.getNode()); + var memberAccess = weaver.getFactory().memberExpr(fieldNode.get(FieldDecl.DECL_NAME), fieldNode.get(FieldDecl.TYPE), (Expr) baseExpr.getNodeImpl()); return CxxJoinpoints.create(memberAccess, weaver, AMemberAccess.class); } - public static AMemberAccess memberAccess(CxxWeaver weaver, AExpression baseExpr, String fieldName, AType fieldType) { - var memberAccess = weaver.getFactory().memberExpr(fieldName, (Type) fieldType.getNode(), (Expr) baseExpr.getNode()); + public static AMemberAccess memberAccess(CxxWeaver weaver, AExpression baseExpr, String fieldName, AType fieldType) { + var memberAccess = weaver.getFactory().memberExpr(fieldName, (Type) fieldType.getNodeImpl(), (Expr) baseExpr.getNodeImpl()); return CxxJoinpoints.create(memberAccess, weaver, AMemberAccess.class); } - public static AUnaryExprOrType sizeof(CxxWeaver weaver, AExpression exprArg) { - var sizeof = weaver.getFactory().sizeof((Expr) exprArg.getNode()); + public static AUnaryExprOrType sizeof(CxxWeaver weaver, AExpression exprArg) { + var sizeof = weaver.getFactory().sizeof((Expr) exprArg.getNodeImpl()); return CxxJoinpoints.create(sizeof, weaver, AUnaryExprOrType.class); } - public static AUnaryExprOrType sizeof(CxxWeaver weaver, AType typeArg) { - var sizeof = weaver.getFactory().sizeof((Type) typeArg.getNode()); + public static AUnaryExprOrType sizeof(CxxWeaver weaver, AType typeArg) { + var sizeof = weaver.getFactory().sizeof((Type) typeArg.getNodeImpl()); return CxxJoinpoints.create(sizeof, weaver, AUnaryExprOrType.class); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/LowLevelApi.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/LowLevelApi.java index 56534f9bd9..26c7a820f0 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/LowLevelApi.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/importable/LowLevelApi.java @@ -17,8 +17,6 @@ import java.util.ArrayList; import java.util.List; -import pt.up.fe.specs.clava.ClavaNode; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; import pt.up.fe.specs.util.SpecsLogs; public class LowLevelApi { @@ -37,20 +35,6 @@ public static List getFields(Object object) { return fieldNames; } - public static Object getValue(Object object, String fieldName) { - try { - Field field = object.getClass().getDeclaredField(fieldName); - field.setAccessible(true); // You might want to set modifier to public first. - Object value = field.get(object); - return value; - } catch ( - IllegalArgumentException | NoSuchFieldException | SecurityException | IllegalAccessException e) { - SpecsLogs.warn("Error message:\n", e); - } - - return null; - } - public static Class getFieldClass(Object object, String fieldName) { try { Field field = object.getClass().getDeclaredField(fieldName); @@ -63,9 +47,4 @@ public static Class getFieldClass(Object object, String fieldName) { return null; } - - public static ClavaNode getNode(ACxxWeaverJoinPoint joinpoint) { - return joinpoint.getNode(); - } - } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAccessSpecifier.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAccessSpecifier.java index 1c3f6c8d17..0a2df3440f 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAccessSpecifier.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAccessSpecifier.java @@ -13,28 +13,24 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.AccessSpecDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AAccessSpecifier; -public class CxxAccessSpecifier extends AAccessSpecifier { - - private final AccessSpecDecl accessSpecifier; +public class CxxAccessSpecifier> extends AAccessSpecifier { public CxxAccessSpecifier(AccessSpecDecl accessSpecifier, CxxWeaver weaver) { - super(new CxxDecl(accessSpecifier, weaver), weaver); - this.accessSpecifier = accessSpecifier; + super(accessSpecifier, weaver); } @Override - public ClavaNode getNode() { - return accessSpecifier; + public AccessSpecDecl getNodeImpl() { + return (AccessSpecDecl) super.getNodeImpl(); } @Override public String getKindImpl() { - return accessSpecifier.get(AccessSpecDecl.ACCESS_SPECIFIER).name().toLowerCase(); + return this.getNodeImpl().get(AccessSpecDecl.ACCESS_SPECIFIER).name().toLowerCase(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxArrayAccess.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxArrayAccess.java index 77a118658c..8074b42698 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxArrayAccess.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxArrayAccess.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.ArraySubscriptExpr; import pt.up.fe.specs.clava.utils.Nameable; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -24,70 +23,66 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVardecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVarref; -public class CxxArrayAccess extends AArrayAccess { - - private final ArraySubscriptExpr arraySub; +public class CxxArrayAccess> extends AArrayAccess { public CxxArrayAccess(ArraySubscriptExpr arraySub, CxxWeaver weaver) { - super(new CxxExpression(arraySub, weaver), weaver); - this.arraySub = arraySub; + super(arraySub, weaver); } @Override - public ClavaNode getNode() { - return arraySub; + public ArraySubscriptExpr getNodeImpl() { + return (ArraySubscriptExpr) super.getNodeImpl(); } @Override - public AExpression getArrayVarImpl() { - return CxxJoinpoints.create(arraySub.getArrayExpr(), getWeaverEngine(), AExpression.class); + public AExpression getArrayVarImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getArrayExpr(), getWeaverEngine(), AExpression.class); } @Override - public AExpression[] getSubscriptArrayImpl() { - return arraySub.getSubscripts().stream() + public AExpression[] getSubscriptImpl() { + return this.getNodeImpl().getSubscripts().stream() .map(expr -> CxxJoinpoints.create(expr, getWeaverEngine(), AExpression.class)) - .toArray(length -> new AExpression[length]); + .toArray(AExpression[]::new); } @Override - public AVardecl getVardeclImpl() { - AExpression arrayVar = getArrayVarImpl(); + public AVardecl getVardeclImpl() { + AExpression arrayVar = getArrayVarImpl(); - if (!(arrayVar instanceof AVarref)) { - return null; + if (arrayVar instanceof AVarref varref) { + return varref.getVardeclImpl(); } - return ((AVarref) arrayVar).getVardeclImpl(); - + return null; } @Override - public ADecl getDeclImpl() { + public ADecl getDeclImpl() { return getVardeclImpl(); } @Override - public AArrayAccess getParentAccessImpl() { - return arraySub.getParentAccess() + public AArrayAccess getParentAccessImpl() { + return this.getNodeImpl().getParentAccess() .map(parentAccess -> CxxJoinpoints.create(parentAccess, getWeaverEngine(), AArrayAccess.class)) .orElse(null); } @Override - public Integer getNumSubscriptsImpl() { - return arraySub.getSubscripts().size(); + public int getNumSubscriptsImpl() { + return this.getNodeImpl().getSubscripts().size(); } @Override public String getNameImpl() { - var arrayVar = getArrayVarImpl().getNode(); + var arrayVar = getArrayVarImpl().getNodeImpl(); - if (!(arrayVar instanceof Nameable)) { - return null; + if (arrayVar instanceof Nameable nameable) { + return nameable.getName(); } - return ((Nameable) arrayVar).getName(); + return null; } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAsmStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAsmStmt.java index 9296ffe2c9..5a0aaa58ba 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAsmStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAsmStmt.java @@ -1,42 +1,33 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.AsmStmt; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AAsmStmt; -public class CxxAsmStmt extends AAsmStmt { +public class CxxAsmStmt> extends AAsmStmt { - private final AsmStmt asmStmt; - - /** - * @param asmStmt - */ public CxxAsmStmt(AsmStmt asmStmt, CxxWeaver weaver) { - super(new CxxStatement(asmStmt, weaver), weaver); - - this.asmStmt = asmStmt; + super(asmStmt, weaver); } @Override - public ClavaNode getNode() { - return asmStmt; + public AsmStmt getNodeImpl() { + return (AsmStmt) super.getNodeImpl(); } @Override - public String[] getClobbersArrayImpl() { - return asmStmt.get(AsmStmt.CLOBBERS).toArray(new String[0]); + public String[] getClobbersImpl() { + return this.getNodeImpl().get(AsmStmt.CLOBBERS).toArray(new String[0]); } @Override - public Boolean getIsSimpleImpl() { - return asmStmt.get(AsmStmt.IS_SIMPLE); + public boolean getIsSimpleImpl() { + return this.getNodeImpl().get(AsmStmt.IS_SIMPLE); } @Override - public Boolean getIsVolatileImpl() { - return asmStmt.get(AsmStmt.IS_VOLATILE); + public boolean getIsVolatileImpl() { + return this.getNodeImpl().get(AsmStmt.IS_VOLATILE); } - } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAttribute.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAttribute.java index 630131e4af..00e856a13b 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAttribute.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxAttribute.java @@ -13,28 +13,24 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.attr.Attribute; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AAttribute; -public class CxxAttribute extends AAttribute { - - private final Attribute attr; +public class CxxAttribute> extends AAttribute { public CxxAttribute(Attribute attr, CxxWeaver weaver) { - super(weaver); - this.attr = attr; + super(attr, weaver); } @Override - public ClavaNode getNode() { - return attr; + public Attribute getNodeImpl() { + return (Attribute) super.getNodeImpl(); } @Override public String getKindImpl() { - var attrName = attr.getKind().name(); + var attrName = this.getNodeImpl().getKind().name(); if (attrName.endsWith("Attr")) { attrName = attrName.substring(0, attrName.length() - "Attr".length()); diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBinaryOp.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBinaryOp.java index 3cfde82223..8ec7fcb8ef 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBinaryOp.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBinaryOp.java @@ -16,7 +16,6 @@ import java.util.Arrays; import java.util.List; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.BinaryOperator; import pt.up.fe.specs.clava.ast.expr.CompoundAssignOperator; import pt.up.fe.specs.clava.ast.expr.Expr; @@ -26,52 +25,48 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ABinaryOp; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; -public class CxxBinaryOp extends ABinaryOp { - - private final BinaryOperator op; +public class CxxBinaryOp> extends ABinaryOp { public CxxBinaryOp(BinaryOperator op, CxxWeaver weaver) { - super(new CxxOp(op, weaver), weaver); - - this.op = op; + super(op, weaver); } @Override - public ClavaNode getNode() { - return op; + public BinaryOperator getNodeImpl() { + return (BinaryOperator) super.getNodeImpl(); } @Override - public AExpression getLeftImpl() { - List left = Arrays.asList((AExpression) CxxJoinpoints.create(op.getLhs(), + public AExpression getLeftImpl() { + List> left = Arrays.asList((AExpression) CxxJoinpoints.create(this.getNodeImpl().getLhs(), getWeaverEngine())); return left.isEmpty() ? null : left.get(0); } @Override - public AExpression getRightImpl() { - List right = Arrays.asList((AExpression) CxxJoinpoints.create(op.getRhs(), + public AExpression getRightImpl() { + List> right = Arrays.asList((AExpression) CxxJoinpoints.create(this.getNodeImpl().getRhs(), getWeaverEngine())); return right.isEmpty() ? null : right.get(0); } @Override - public Boolean getIsAssignmentImpl() { - return op.getOp() == BinaryOperatorKind.Assign || op instanceof CompoundAssignOperator; + public boolean getIsAssignmentImpl() { + return this.getNodeImpl().getOp() == BinaryOperatorKind.Assign || this.getNodeImpl() instanceof CompoundAssignOperator; } @Override - public Boolean getIsBitwiseImpl() { - return op.getOp().isBitwise(); + public boolean getIsBitwiseImpl() { + return this.getNodeImpl().getOp().isBitwise(); } @Override - public void setLeftImpl(AExpression left) { - op.setLhs((Expr) left.getNode()); + public void setLeftImpl(AExpression left) { + this.getNodeImpl().setLhs((Expr) left.getNodeImpl()); } @Override - public void setRightImpl(AExpression right) { - op.setRhs((Expr) right.getNode()); + public void setRightImpl(AExpression right) { + this.getNodeImpl().setRhs((Expr) right.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBody.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBody.java index 8e20baa4af..e85614fd9c 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBody.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBody.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.CompoundStmt; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ABody; -public class CxxBody extends ABody { - - private final CompoundStmt scope; +public class CxxBody> extends ABody { public CxxBody(CompoundStmt scope, CxxWeaver weaver) { - super(new CxxScope(scope, weaver), weaver); - this.scope = scope; + super(scope, weaver); } @Override - public ClavaNode getNode() { - return scope; + public CompoundStmt getNodeImpl() { + return (CompoundStmt) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBoolLiteral.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBoolLiteral.java index a67a326804..90bbc992bf 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBoolLiteral.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBoolLiteral.java @@ -13,30 +13,24 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.CXXBoolLiteralExpr; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ABoolLiteral; -public class CxxBoolLiteral extends ABoolLiteral { - - private final CXXBoolLiteralExpr literal; +public class CxxBoolLiteral> extends ABoolLiteral { public CxxBoolLiteral(CXXBoolLiteralExpr literal, CxxWeaver weaver) { - super(new CxxLiteral(literal, weaver), weaver); - - this.literal = literal; + super(literal, weaver); } @Override - public ClavaNode getNode() { - return literal; + public CXXBoolLiteralExpr getNodeImpl() { + return (CXXBoolLiteralExpr) super.getNodeImpl(); } @Override - public Boolean getValueImpl() { - return literal.get(CXXBoolLiteralExpr.VALUE); + public boolean getValueImpl() { + return this.getNodeImpl().get(CXXBoolLiteralExpr.VALUE); } - } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBreak.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBreak.java index 11f3d5a155..619ad8ead9 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBreak.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxBreak.java @@ -13,31 +13,26 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.BreakStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ABreak; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; -public class CxxBreak extends ABreak { - - private final BreakStmt breakStmt; +public class CxxBreak> extends ABreak { public CxxBreak(BreakStmt breakStmt, CxxWeaver weaver) { - super(new CxxStatement(breakStmt, weaver), weaver); - - this.breakStmt = breakStmt; + super(breakStmt, weaver); } @Override - public ClavaNode getNode() { - return breakStmt; + public BreakStmt getNodeImpl() { + return (BreakStmt) super.getNodeImpl(); } @Override - public AStatement getEnclosingStmtImpl() { - return CxxJoinpoints.create(breakStmt.getEnclosingStmt(), getWeaverEngine(), AStatement.class); + public AStatement getEnclosingStmtImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getEnclosingStmt(), getWeaverEngine(), AStatement.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCall.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCall.java index b535eef9bd..bf442803bd 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCall.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCall.java @@ -40,32 +40,30 @@ import pt.up.fe.specs.util.SpecsLogs; import pt.up.fe.specs.util.treenode.NodeInsertUtils; -public class CxxCall extends ACall { - - private final CallExpr call; +public class CxxCall> extends ACall { public CxxCall(CallExpr call, CxxWeaver weaver) { - super(new CxxExpression(call, weaver), weaver); - - this.call = call; + super(call, weaver); } @Override - public String getNameImpl() { - return call.getCalleeNameTry().orElse(null); + public CallExpr getNodeImpl() { + return (CallExpr) super.getNodeImpl(); } @Override - public Integer getNumArgsImpl() { - return call.getArgs().size(); + public String getNameImpl() { + return this.getNodeImpl().getCalleeNameTry().orElse(null); } @Override - public CallExpr getNode() { - return call; + public int getNumArgsImpl() { + return this.getNodeImpl().getArgs().size(); } - public void extractImpl(String variableName, Boolean declareVariable) { + public void extractImpl(String variableName, boolean declareVariable) { + var call = this.getNodeImpl(); + // Check that call is inside an ExprStmt if (!(call.getParent() instanceof ExprStmt)) { SpecsLogs.msgInfo("Action currently supported only for calls alone in a statement. Skipping for code:" @@ -82,19 +80,11 @@ public void extractImpl(String variableName, Boolean declareVariable) { // DeclStmt -> VarDecl -> Call if (declareVariable) { - // VarDeclData varDeclData = new VarDeclData(StorageClass.NONE, TLSKind.NONE, false, false, - // InitializationStyle.CINIT, false); - // DeclData declData = new DeclData(false, false, true, false, false, false); - // VarDecl varDecl = ClavaNodeFactory.varDecl(varDeclData, variableName, returnType, declData, - // call.getInfo(), - // call); - VarDecl varDecl = getFactory().varDecl(variableName, returnType); varDecl.setInit(call); varDecl.set(VarDecl.IS_USED); DeclStmt declStmt = call.getFactoryWithNode().declStmt(varDecl); - // DeclStmt declStmt = ClavaNodeFactory.declStmt(call.getInfo(), Arrays.asList(varDecl)); // Replace stmt NodeInsertUtils.replace(exprStmt, declStmt, true); @@ -105,83 +95,65 @@ public void extractImpl(String variableName, Boolean declareVariable) { Expr varExpr = getWeaverEngine().getFactory().literalExpr(variableName, returnType); BinaryOperator assign = getWeaverEngine().getFactory().binaryOperator(BinaryOperatorKind.Assign, returnType, varExpr, call); - // BinaryOperator assign = ClavaNodeFactory.binaryOperator(BinaryOperatorKind.ASSIGN, new - // ExprData(returnType), - // call.getInfo(), varExpr, call); ExprStmt newStmt = getWeaverEngine().getFactory().exprStmt(assign); // Replace stmt NodeInsertUtils.replace(exprStmt, newStmt, true); /* - ExprStmt: (0x46d4420) - BinaryOperator: (0x46d4420) types:int, valueKind:L_VALUE, op:ASSIGNMENT - DeclRefExpr: (0x46d43d8) types:int, valueKind:L_VALUE, refType:Var, refName:samples, type2: - IntegerLiteral: (0x46d4400) types:int, valueKind:R_VALUE + * ExprStmt: (0x46d4420) + * BinaryOperator: (0x46d4420) types:int, valueKind:L_VALUE, op:ASSIGNMENT + * DeclRefExpr: (0x46d43d8) types:int, valueKind:L_VALUE, refType:Var, + * refName:samples, type2: + * IntegerLiteral: (0x46d4400) types:int, valueKind:R_VALUE */ } } @Override - public AType getTypeImpl() { + public AType getTypeImpl() { + var call = this.getNodeImpl(); if (call instanceof CXXMemberCallExpr) { return CxxJoinpoints.create(((CXXMemberCallExpr) call).getType(), getWeaverEngine(), AType.class); } // Return the type of the function (return type), after desugaring Type calleeType = call.getCallee().getType().desugarAll(); - // System.out.println("CALLEE:" + call.getCallee()); // If PointerType to FunctionType, remove pointer - // if (calleeType instanceof PointerType && ((PointerType) calleeType).getPointeeType() instanceof FunctionType) - // { - // calleeType = ((PointerType) calleeType).getPointeeType(); - // } - // System.out.println("CALLEE TYPE:" + calleeType); if (calleeType instanceof FunctionType) { return CxxJoinpoints.create(((FunctionType) calleeType).getReturnType(), getWeaverEngine(), AType.class); } - /* - if (!(calleeType instanceof LiteralType)) { - LoggingUtils - .msgWarn("Expected LiteralType, got '" + calleeType.getClass().getSimpleName() + "'. Check if ok"); - } - */ - return CxxJoinpoints.create(calleeType, getWeaverEngine(), AType.class); } @Override - public String[] getMemberNamesArrayImpl() { - return call.getCallMemberNames().toArray(new String[0]); + public String[] getMemberNamesImpl() { + return this.getNodeImpl().getCallMemberNames().toArray(new String[0]); } @Override public void setNameImpl(String name) { - call.setCallName(name); + this.getNodeImpl().setCallName(name); } @Override - public AFunction getDeclarationImpl() { - return call.getPrototypes().stream() + public AFunction getDeclarationImpl() { + return this.getNodeImpl().getPrototypes().stream() .map(decl -> CxxJoinpoints.create(decl, getWeaverEngine(), AFunction.class)) .findFirst() .orElse(null); - // return call.getFunctionDecl().map(FunctionDecl::getPrototypes) - // .map(decl -> CxxJoinpoints.create(decl, AFunction.class)).orElse(null); - // var declarations = getDeclarationsArrayImpl(); - // return declarations.length != 0 ? declarations[0] : null; - // return call.getDeclaration().map(decl -> (AFunction) CxxJoinpoints.create(decl)).orElse(null); } @Override - public AFunction getDefinitionImpl() { - return call.getDefinition().map(decl -> CxxJoinpoints.create(decl, getWeaverEngine(), AFunction.class)).orElse(null); + public AFunction getDefinitionImpl() { + return this.getNodeImpl().getDefinition().map(decl -> CxxJoinpoints.create(decl, getWeaverEngine(), AFunction.class)) + .orElse(null); } @Override - public AExpression[] getArgsArrayImpl() { - return call.getArgs() + public AExpression[] getArgsImpl() { + return this.getNodeImpl().getArgs() .stream() // .map(Expr::getCode) .map(arg -> CxxJoinpoints.create(arg, getWeaverEngine(), AExpression.class)) @@ -190,14 +162,13 @@ public AExpression[] getArgsArrayImpl() { } @Override - public AExpression[] getArgListArrayImpl() { - return getArgsArrayImpl(); + public AExpression[] getArgListImpl() { + return getArgsImpl(); } @Override - public AType getReturnTypeImpl() { - - return CxxJoinpoints.create(call.getType(), getWeaverEngine(), AType.class); + public AType getReturnTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getType(), getWeaverEngine(), AType.class); } @Override @@ -207,6 +178,8 @@ public void wrapImpl(String name) { @Override public boolean inlineImpl() { + var call = this.getNodeImpl(); + // Only inline if call is associated to an App if (!call.getAppTry().isPresent()) { SpecsLogs.msgInfo("Tried to inline call that is not associated to an app"); @@ -214,98 +187,78 @@ public boolean inlineImpl() { } return call.getApp().inline(call); - // call.getAncestor(App.class).inline(call); - // new CallInliner(call).inline(); } @Override public void setArgFromStringImpl(int index, String expr) { // Get arg of equivalent index, to extract type - Expr arg = call.getArgs().get(index); + Expr arg = this.getNodeImpl().getArgs().get(index); Expr literalExpr = getWeaverEngine().getFactory().literalExpr(expr, arg.getExprType()); setArgImpl(index, CxxJoinpoints.create(literalExpr, getWeaverEngine(), AExpression.class)); } @Override - public void addArgImpl(String arg, AType type) { + public void addArgImpl(String arg, AType type) { Type processedType; - + if (type == null) { processedType = getWeaverEngine().getFactory().dummyType("from $call.addArg()"); } else { - processedType = (Type) type.getNode(); + processedType = (Type) type.getNodeImpl(); } - - call.addArgument(arg, processedType); + + this.getNodeImpl().addArgument(arg, processedType); } @Override public void addArgImpl(String arg, String type) { - call.addArgument(arg, getWeaverEngine().getFactory().literalType(type)); + this.getNodeImpl().addArgument(arg, getWeaverEngine().getFactory().literalType(type)); } @Override - public void setArgImpl(int index, AExpression expr) { - // Check num args - // int numArgs = getArgListArrayImpl().length; - // if (index >= 0 && index < numArgs) { - // SpecsLogs.msgInfo( - // "Not setting call argument, index is '" + index + "' and call has " + numArgs + " arguments"); - // return; - // } - - call.setArgument(index, (Expr) expr.getNode()); + public void setArgImpl(int index, AExpression expr) { + this.getNodeImpl().setArgument(index, (Expr) expr.getNodeImpl()); } @Override - public AExpression getArgImpl(int index) { - call.checkIndex(index); - Expr arg = call.getArgs().get(index); + public AExpression getGetArgImpl(int index) { + this.getNodeImpl().checkIndex(index); + Expr arg = this.getNodeImpl().getArgs().get(index); return CxxJoinpoints.create(arg, getWeaverEngine(), AExpression.class); - } @Override - public Boolean getIsMemberAccessImpl() { - return call instanceof CXXMemberCallExpr; + public boolean getIsMemberAccessImpl() { + return this.getNodeImpl() instanceof CXXMemberCallExpr; } @Override - public AMemberAccess getMemberAccessImpl() { - if (!(call instanceof CXXMemberCallExpr)) { + public AMemberAccess getMemberAccessImpl() { + if (!(this.getNodeImpl() instanceof CXXMemberCallExpr)) { return null; } - var callee = ((CXXMemberCallExpr) call).getCallee(); - - // if (!(callee instanceof MemberExpr)) { - // return null; - // } + var callee = ((CXXMemberCallExpr) this.getNodeImpl()).getCallee(); MemberExpr memberExpr = callee; - // MemberExpr memberExpr = ((CXXMemberCallExpr) call).getCallee(); - return CxxJoinpoints.create(memberExpr, getWeaverEngine(), AMemberAccess.class); - } @Override - public AFunctionType getFunctionTypeImpl() { - return call.getFunctionType() + public AFunctionType getFunctionTypeImpl() { + return this.getNodeImpl().getFunctionType() .map(type -> CxxJoinpoints.create(type, getWeaverEngine(), AFunctionType.class)) .orElse(null); - - // return (AType) CxxJoinpoints.create(call.getFunctionType(), this); } @Override - public Boolean getIsStmtCallImpl() { - return call.isStmtCall(); + public boolean getIsStmtCallImpl() { + return this.getNodeImpl().isStmtCall(); } @Override - public AFunction getFunctionImpl() { + public AFunction getFunctionImpl() { // First, try the implementation var definition = getDefinitionImpl(); @@ -315,47 +268,32 @@ public AFunction getFunctionImpl() { // Implementation not found return declaration return getDeclarationImpl(); - - // return call.getFunctionDecl() - // .map(fDecl -> CxxJoinpoints.create(fDecl, AFunction.class)) - // .orElse(null); } @Override public String getSignatureImpl() { - AFunction function = getFunctionImpl(); + AFunction function = getFunctionImpl(); if (function != null) { return function.getSignatureImpl(); } - // if (getDeclarationImpl() != null) { - // System.out.println("DECL SIG:" + getDeclarationImpl().getSignatureImpl()); - // } - // System.out.println("DECL:" + getDeclarationImpl()); - // System.out.println("DEF:" + getDefinitionImpl()); - return "<" + getNameImpl() + ">"; } @Override - public AFunction getDeclImpl() { - return call.getFunctionDecl() + public AFunction getDeclImpl() { + return this.getNodeImpl().getFunctionDecl() .map(fDecl -> CxxJoinpoints.create(fDecl, getWeaverEngine(), AFunction.class)) .orElse(null); } @Override - public AFunction getDirectCalleeImpl() { - return call.get(CallExpr.DIRECT_CALLEE) + public AFunction getDirectCalleeImpl() { + return this.getNodeImpl().get(CallExpr.DIRECT_CALLEE) .map(callee -> CxxJoinpoints.create(callee, getWeaverEngine(), AFunction.class)) .orElse(null); } - - // @Override - // public String getSignatureImpl() { - // return call.getSignature(); - // } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCase.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCase.java index df7c94bc46..36ef631d31 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCase.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCase.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.SwitchCase; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; @@ -21,33 +20,30 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; -public class CxxCase extends ACase { - - private final SwitchCase caseStmt; +public class CxxCase> extends ACase { public CxxCase(SwitchCase caseStmt, CxxWeaver weaver) { - super(new CxxSwitchCase(caseStmt, weaver), weaver); - this.caseStmt = caseStmt; + super(caseStmt, weaver); } @Override - public ClavaNode getNode() { - return caseStmt; + public SwitchCase getNodeImpl() { + return (SwitchCase) super.getNodeImpl(); } @Override - public Boolean getIsDefaultImpl() { - return caseStmt.isDefaultCase(); + public boolean getIsDefaultImpl() { + return this.getNodeImpl().isDefaultCase(); } @Override - public Boolean getIsEmptyImpl() { - return caseStmt.isEmptyCase(); + public boolean getIsEmptyImpl() { + return this.getNodeImpl().isEmptyCase(); } @Override - public AStatement getNextInstructionImpl() { - var nextInst = caseStmt.nextExecutedInstruction(); + public AStatement getNextInstructionImpl() { + var nextInst = this.getNodeImpl().nextExecutedInstruction(); if (nextInst == null) { return null; } @@ -56,18 +52,18 @@ public AStatement getNextInstructionImpl() { } @Override - public AStatement[] getInstructionsArrayImpl() { - return CxxJoinpoints.create(caseStmt.getInstructions(), getWeaverEngine(), AStatement.class); + public AStatement[] getInstructionsImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getInstructions(), getWeaverEngine(), AStatement.class); } @Override - public ACase getNextCaseImpl() { - return CxxJoinpoints.create(caseStmt.nextCase(), getWeaverEngine(), ACase.class); + public ACase getNextCaseImpl() { + return CxxJoinpoints.create(this.getNodeImpl().nextCase(), getWeaverEngine(), ACase.class); } @Override - public AExpression[] getValuesArrayImpl() { - return CxxJoinpoints.create(caseStmt.getValues(), getWeaverEngine(), AExpression.class); + public AExpression[] getValuesImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getValues(), getWeaverEngine(), AExpression.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCast.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCast.java index bc4a3c52e6..8494987a55 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCast.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCast.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.CastExpr; import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -24,51 +23,47 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVardecl; -public class CxxCast extends ACast { - - private final CastExpr cast; +public class CxxCast> extends ACast { public CxxCast(CastExpr cast, CxxWeaver weaver) { - super(new CxxExpression(cast, weaver), weaver); - - this.cast = cast; + super(cast, weaver); } @Override - public ClavaNode getNode() { - return cast; + public CastExpr getNodeImpl() { + return (CastExpr) super.getNodeImpl(); } @Override - public Boolean getIsImplicitCastImpl() { + public boolean getIsImplicitCastImpl() { throw new RuntimeException("cast.isImplicitCast deprecated, please use instead expr.implicitCast"); } @Override - public AType getFromTypeImpl() { - Type fromType = cast.getSubExpr().getType(); + public AType getFromTypeImpl() { + Type fromType = this.getNodeImpl().getSubExpr().getType(); return CxxJoinpoints.create(fromType, getWeaverEngine(), AType.class); } @Override - public AType getToTypeImpl() { - return CxxJoinpoints.create(cast.getCastType(), getWeaverEngine(), AType.class); + public AType getToTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getCastType(), getWeaverEngine(), AType.class); } @Override - public AVardecl getVardeclImpl() { - return CxxJoinpoints.create(cast.getSubExpr(), getWeaverEngine(), AExpression.class).getVardeclImpl(); + public AVardecl getVardeclImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getSubExpr(), getWeaverEngine(), AExpression.class).getVardeclImpl(); } @Override - public ADecl getDeclImpl() { + public ADecl getDeclImpl() { return getVardeclImpl(); } @Override - public AExpression getSubExprImpl() { - return CxxJoinpoints.create(cast.getSubExpr(), getWeaverEngine(), AExpression.class); + public AExpression getSubExprImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getSubExpr(), getWeaverEngine(), AExpression.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxClass.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxClass.java index e5febc5a74..f678e74765 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxClass.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxClass.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.CXXMethodDecl; import pt.up.fe.specs.clava.ast.decl.CXXRecordDecl; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -22,102 +21,75 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AClass; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AMethod; -public class CxxClass extends AClass { - - private final CXXRecordDecl cxxRecordDecl; +public class CxxClass> extends AClass { public CxxClass(CXXRecordDecl cxxRecordDecl, CxxWeaver weaver) { - super(new CxxStruct(cxxRecordDecl, weaver), weaver); - - this.cxxRecordDecl = cxxRecordDecl; - } - - public Boolean isAbstract() { - return (Boolean) this.getIsAbstract(); - /* - return this.cxxRecordDecl.getMethods().stream() - .filter(method -> !(method instanceof CXXDestructorDecl)) - .anyMatch(method -> {/* - System.err.println(" -> " + method.getFullyQualifiedName() - + " " + method.get(CXXMethodDecl.IS_VIRTUAL).booleanValue() - + " " + method.get(CXXMethodDecl.IS_PURE).booleanValue()); - /** / - // System.err.println(method.getCode()); - - return method.get(CXXMethodDecl.IS_PURE).booleanValue(); - }); - */ + super(cxxRecordDecl, weaver); } @Override - public ClavaNode getNode() { - return cxxRecordDecl; + public CXXRecordDecl getNodeImpl() { + return (CXXRecordDecl) super.getNodeImpl(); } @Override - public AMethod[] getMethodsArrayImpl() { - return CxxSelects.select(getWeaverEngine(), AMethod.class, cxxRecordDecl.getMethods(), false, node -> true).toArray(new AMethod[0]); + public AMethod[] getMethodsImpl() { + return CxxSelects.select(getWeaverEngine(), AMethod.class, this.getNodeImpl().getMethods(), false, node -> true); } @Override - public void addMethodImpl(AMethod method) { - cxxRecordDecl.addMethod((CXXMethodDecl) method.getNode()); + public void addMethodImpl(AMethod method) { + this.getNodeImpl().addMethod((CXXMethodDecl) method.getNodeImpl()); } @Override - public AClass[] getBasesArrayImpl() { + public AClass[] getBasesImpl() { - return cxxRecordDecl.getBases().stream() + return this.getNodeImpl().getBases().stream() .map(decl -> CxxJoinpoints.create(decl, getWeaverEngine(), AClass.class)) // Collect to array .toArray(size -> new AClass[size]); - - // return cxxRecordDecl.get(CXXRecordDecl.RECORD_BASES).stream() - // // Map Decl - // .map(baseSpec -> CxxJoinpoints.create(baseSpec.getBaseDecl(cxxRecordDecl), AClass.class)) - // // Collect to array - // .toArray(size -> new AClass[size]); } @Override - public AMethod[] getAllMethodsArrayImpl() { - return CxxJoinpoints.create(cxxRecordDecl.getAllMethods(false), getWeaverEngine(), AMethod.class); + public AMethod[] getAllMethodsImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getAllMethods(false), getWeaverEngine(), AMethod.class); } @Override - public AClass[] getAllBasesArrayImpl() { - return CxxJoinpoints.create(cxxRecordDecl.getAllBases(), getWeaverEngine(), AClass.class); + public AClass[] getAllBasesImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getAllBases(), getWeaverEngine(), AClass.class); } @Override - public Boolean getIsAbstractImpl() { - return cxxRecordDecl.isAbstract(); + public boolean getIsAbstractImpl() { + return this.getNodeImpl().isAbstract(); } @Override - public Boolean getIsInterfaceImpl() { - return cxxRecordDecl.isInterface(); + public boolean getIsInterfaceImpl() { + return this.getNodeImpl().isInterface(); } @Override - public AClass[] getPrototypesArrayImpl() { - return cxxRecordDecl.getDeclarations().stream() + public AClass[] getPrototypesImpl() { + return this.getNodeImpl().getDeclarations().stream() .map(node -> CxxJoinpoints.create(node, getWeaverEngine(), AClass.class)) - .toArray(size -> new AClass[size]); + .toArray(AClass[]::new); } @Override - public AClass getImplementationImpl() { - return cxxRecordDecl.getDefinition() + public AClass getImplementationImpl() { + return this.getNodeImpl().getDefinition() .map(node -> CxxJoinpoints.create(node, getWeaverEngine(), AClass.class)) .orElse(null); } @Override - public AClass getCanonicalImpl() { + public AClass getCanonicalImpl() { // First, try the implementation var implementation = getImplementationImpl(); @@ -126,7 +98,7 @@ public AClass getCanonicalImpl() { } // Implementation not found return prototype - var prototypes = getPrototypesArrayImpl(); + var prototypes = getPrototypesImpl(); if (prototypes.length == 0) { return null; @@ -136,8 +108,8 @@ public AClass getCanonicalImpl() { } @Override - public Boolean getIsCanonicalImpl() { - return cxxRecordDecl.equals(getCanonicalImpl().getNode()); + public boolean getIsCanonicalImpl() { + return this.getNodeImpl().equals(getCanonicalImpl().getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxClavaException.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxClavaException.java deleted file mode 100644 index c9fc1b57da..0000000000 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxClavaException.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright 2019 SPeCS. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ - -package pt.up.fe.specs.clava.weaver.joinpoints; - -import pt.up.fe.specs.clava.ClavaNode; -import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AClavaException; - -public class CxxClavaException extends AClavaException { - - private final Throwable exception; - - public CxxClavaException(Throwable exception, CxxWeaver weaver) { - super(weaver); - this.exception = exception; - } - - @Override - public ClavaNode getNode() { - throw new RuntimeException("ClavaException join point does not have an AST node"); - } - - @Override - public String getMessageImpl() { - return exception.getMessage(); - } - - @Override - public Object getExceptionImpl() { - return exception; - } - - @Override - public String getExceptionTypeImpl() { - return exception.getClass().getSimpleName(); - } -} diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxComment.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxComment.java index 2ba2cea606..accc442f9b 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxComment.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxComment.java @@ -13,33 +13,29 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.comment.Comment; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AComment; -public class CxxComment extends AComment { - - private final Comment comment; +public class CxxComment> extends AComment { public CxxComment(Comment comment, CxxWeaver weaver) { - super(weaver); - this.comment = comment; + super(comment, weaver); } @Override - public ClavaNode getNode() { - return comment; + public Comment getNodeImpl() { + return (Comment) super.getNodeImpl(); } @Override public String getTextImpl() { - return comment.getText(); + return this.getNodeImpl().getText(); } @Override public void setTextImpl(String text) { - comment.setText(text); + this.getNodeImpl().setText(text); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxContinue.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxContinue.java index 32f73d42ba..67f387fac6 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxContinue.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxContinue.java @@ -13,24 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.ContinueStmt; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AContinue; -public class CxxContinue extends AContinue { - - private final ContinueStmt continueStmt; +public class CxxContinue> extends AContinue { public CxxContinue(ContinueStmt continueStmt, CxxWeaver weaver) { - super(new CxxStatement(continueStmt, weaver), weaver); - - this.continueStmt = continueStmt; + super(continueStmt, weaver); } @Override - public ClavaNode getNode() { - return continueStmt; + public ContinueStmt getNodeImpl() { + return (ContinueStmt) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CXXCudaKernelCall.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCudaKernelCall.java similarity index 53% rename from ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CXXCudaKernelCall.java rename to ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCudaKernelCall.java index ca6d8949df..d3504000ae 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CXXCudaKernelCall.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxCudaKernelCall.java @@ -2,7 +2,6 @@ import java.util.Arrays; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.CUDAKernelCallExpr; import pt.up.fe.specs.clava.ast.expr.Expr; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -12,36 +11,32 @@ import pt.up.fe.specs.clava.weaver.importable.AstFactory; import pt.up.fe.specs.util.SpecsCollections; -public class CXXCudaKernelCall extends ACudaKernelCall { +public class CxxCudaKernelCall> extends ACudaKernelCall { - private final CUDAKernelCallExpr kernelCall; - - public CXXCudaKernelCall(CUDAKernelCallExpr kernelCall, CxxWeaver weaver) { - super(new CxxCall(kernelCall, weaver), weaver); - - this.kernelCall = kernelCall; + public CxxCudaKernelCall(CUDAKernelCallExpr kernelCall, CxxWeaver weaver) { + super(kernelCall, weaver); } @Override - public ClavaNode getNode() { - return kernelCall; + public CUDAKernelCallExpr getNodeImpl() { + return (CUDAKernelCallExpr) super.getNodeImpl(); } @Override - public AExpression[] getConfigArrayImpl() { - return CxxJoinpoints.create(kernelCall.getConfiguration(), getWeaverEngine(), AExpression.class); + public AExpression[] getConfigImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getConfiguration(), getWeaverEngine(), AExpression.class); } @Override - public void setConfigImpl(AExpression[] args) { - kernelCall.setConfiguration(SpecsCollections.toList(args, jp -> (Expr) jp.getNode())); + public void setConfigImpl(AExpression[] args) { + this.getNodeImpl().setConfiguration(SpecsCollections.toList(args, jp -> (Expr) jp.getNodeImpl())); } @Override public void setConfigFromStringsImpl(String[] args) { var exprArray = Arrays.stream(args) .map(arg -> AstFactory.exprLiteral(getWeaverEngine(), arg)) - .toArray(size -> new AExpression[size]); + .toArray(AExpression[]::new); setConfigImpl(exprArray); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDecl.java index 269af9c21a..7deae923a8 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDecl.java @@ -13,31 +13,27 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.Decl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AAttribute; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADecl; -public class CxxDecl extends ADecl { - - private final Decl decl; +public class CxxDecl> extends ADecl { public CxxDecl(Decl decl, CxxWeaver weaver) { - super(weaver); - this.decl = decl; + super(decl, weaver); } @Override - public ClavaNode getNode() { - return decl; + public Decl getNodeImpl() { + return (Decl) super.getNodeImpl(); } @Override - public AAttribute[] getAttrsArrayImpl() { - return decl.get(Decl.ATTRIBUTES).stream() - .map(attr -> new CxxAttribute(attr, getWeaverEngine())) - .toArray(size -> new AAttribute[size]); + public AAttribute[] getAttrsImpl() { + return this.getNodeImpl().get(Decl.ATTRIBUTES).stream() + .map(attr -> new CxxAttribute<>(attr, getWeaverEngine())) + .toArray(AAttribute[]::new); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclStmt.java index 09d32ec1ea..c489c10108 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclStmt.java @@ -13,30 +13,26 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.DeclStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADeclStmt; -public class CxxDeclStmt extends ADeclStmt { - - private final DeclStmt declStmt; +public class CxxDeclStmt> extends ADeclStmt { public CxxDeclStmt(DeclStmt declStmt, CxxWeaver weaver) { - super(new CxxStatement(declStmt, weaver), weaver); - this.declStmt = declStmt; + super(declStmt, weaver); } @Override - public ClavaNode getNode() { - return declStmt; + public DeclStmt getNodeImpl() { + return (DeclStmt) super.getNodeImpl(); } @Override - public ADecl[] getDeclsArrayImpl() { - return CxxJoinpoints.create(declStmt.getDecls(), getWeaverEngine(), ADecl.class); + public ADecl[] getDeclsImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getDecls(), getWeaverEngine(), ADecl.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclarator.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclarator.java index ae1874df1a..bd9c7438dd 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclarator.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeclarator.java @@ -13,24 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.DeclaratorDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADeclarator; -public class CxxDeclarator extends ADeclarator { - - private final DeclaratorDecl declaratorDecl; +public class CxxDeclarator> extends ADeclarator { public CxxDeclarator(DeclaratorDecl declaratorDecl, CxxWeaver weaver) { - super(new CxxNamedDecl(declaratorDecl, weaver), weaver); - - this.declaratorDecl = declaratorDecl; + super(declaratorDecl, weaver); } @Override - public ClavaNode getNode() { - return declaratorDecl; + public DeclaratorDecl getNodeImpl() { + return (DeclaratorDecl) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDefault.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDefault.java index 6a7d6872ed..2c6f2c8857 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDefault.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDefault.java @@ -1,21 +1,17 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.DefaultStmt; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADefault; -public class CxxDefault extends ADefault { - - private final DefaultStmt defaultStmt; +public class CxxDefault> extends ADefault { public CxxDefault(DefaultStmt defaultStmt, CxxWeaver weaver) { - super(new CxxSwitchCase(defaultStmt, weaver), weaver); - this.defaultStmt = defaultStmt; + super(defaultStmt, weaver); } @Override - public ClavaNode getNode() { - return defaultStmt; + public DefaultStmt getNodeImpl() { + return (DefaultStmt) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeleteExpr.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeleteExpr.java index f189fa1e5f..e83f20cc60 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeleteExpr.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxDeleteExpr.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.CXXDeleteExpr; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADeleteExpr; -public class CxxDeleteExpr extends ADeleteExpr { - - private final CXXDeleteExpr deleteExpr; +public class CxxDeleteExpr> extends ADeleteExpr { public CxxDeleteExpr(CXXDeleteExpr deleteExpr, CxxWeaver weaver) { - super(new CxxExpression(deleteExpr, weaver), weaver); - this.deleteExpr = deleteExpr; + super(deleteExpr, weaver); } @Override - public ClavaNode getNode() { - return deleteExpr; + public CXXDeleteExpr getNodeImpl() { + return (CXXDeleteExpr) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmpty.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmpty.java index 882ff0e8f5..3a4f9f91f1 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmpty.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmpty.java @@ -17,18 +17,15 @@ import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AEmpty; -public class CxxEmpty extends AEmpty { - - private final ClavaNode emptyNode; +public class CxxEmpty> extends AEmpty { public CxxEmpty(ClavaNode emptyNode, CxxWeaver weaver) { - super(weaver); - this.emptyNode = emptyNode; + super(emptyNode, weaver); } @Override - public ClavaNode getNode() { - return emptyNode; + public ClavaNode getNodeImpl() { + return (ClavaNode) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmptyStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmptyStmt.java index bed95388bf..5a9d64f944 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmptyStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEmptyStmt.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.EmptyStmt; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AEmptyStmt; -public class CxxEmptyStmt extends AEmptyStmt { - - private final EmptyStmt emptyStmt; +public class CxxEmptyStmt> extends AEmptyStmt { public CxxEmptyStmt(EmptyStmt emptyStmt, CxxWeaver weaver) { - super(new CxxStatement(emptyStmt, weaver), weaver); - this.emptyStmt = emptyStmt; + super(emptyStmt, weaver); } @Override - public ClavaNode getNode() { - return emptyStmt; + public EmptyStmt getNodeImpl() { + return (EmptyStmt) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumDecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumDecl.java index fc544b4fba..958823b8a7 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumDecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumDecl.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.EnumConstantDecl; import pt.up.fe.specs.clava.ast.decl.EnumDecl; import pt.up.fe.specs.clava.weaver.CxxSelects; @@ -21,23 +20,20 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AEnumDecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AEnumeratorDecl; -public class CxxEnumDecl extends AEnumDecl { - - private final EnumDecl enumDecl; +public class CxxEnumDecl> extends AEnumDecl { public CxxEnumDecl(EnumDecl enumDecl, CxxWeaver weaver) { - super(new CxxNamedDecl(enumDecl, weaver), weaver); - this.enumDecl = enumDecl; + super(enumDecl, weaver); } @Override - public ClavaNode getNode() { - return enumDecl; + public EnumDecl getNodeImpl() { + return (EnumDecl) super.getNodeImpl(); } @Override - public AEnumeratorDecl[] getEnumeratorsArrayImpl() { - return CxxSelects.select(getWeaverEngine(), AEnumeratorDecl.class, enumDecl.getChildren(), false, EnumConstantDecl.class).toArray(new AEnumeratorDecl[0]); + public AEnumeratorDecl[] getEnumeratorsImpl() { + return CxxSelects.select(getWeaverEngine(), AEnumeratorDecl.class, this.getNodeImpl().getChildren(), false, EnumConstantDecl.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumeratorDecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumeratorDecl.java index 0b048e1b51..79de88c645 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumeratorDecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxEnumeratorDecl.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.EnumConstantDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AEnumeratorDecl; -public class CxxEnumeratorDecl extends AEnumeratorDecl { - - private final EnumConstantDecl enumConstantDecl; +public class CxxEnumeratorDecl> extends AEnumeratorDecl { public CxxEnumeratorDecl(EnumConstantDecl enumDecl, CxxWeaver weaver) { - super(new CxxNamedDecl(enumDecl, weaver), weaver); - this.enumConstantDecl = enumDecl; + super(enumDecl, weaver); } @Override - public ClavaNode getNode() { - return enumConstantDecl; + public EnumConstantDecl getNodeImpl() { + return (EnumConstantDecl) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExprStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExprStmt.java index 2a5d03ef2a..04bee9f4e2 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExprStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExprStmt.java @@ -13,31 +13,26 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.ExprStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExprStmt; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; -public class CxxExprStmt extends AExprStmt { - - private final ExprStmt exprStmt; +public class CxxExprStmt> extends AExprStmt { public CxxExprStmt(ExprStmt exprStmt, CxxWeaver weaver) { - super(new CxxStatement(exprStmt, weaver), weaver); - - this.exprStmt = exprStmt; + super(exprStmt, weaver); } @Override - public ClavaNode getNode() { - return exprStmt; + public ExprStmt getNodeImpl() { + return (ExprStmt) super.getNodeImpl(); } @Override - public AExpression getExprImpl() { - return CxxJoinpoints.create(exprStmt.getExpr(), getWeaverEngine(), AExpression.class); + public AExpression getExprImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getExpr(), getWeaverEngine(), AExpression.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExpression.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExpression.java index 4bb7b4e537..d89bbf0fe6 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExpression.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxExpression.java @@ -13,91 +13,49 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import pt.up.fe.specs.clava.ast.expr.Expr; import pt.up.fe.specs.clava.ast.stmt.ExprStmt; import pt.up.fe.specs.clava.weaver.CxxAttributes; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.*; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ACast; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADecl; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVardecl; +import pt.up.fe.specs.clava.weaver.enums.ExpressionUse; +import pt.up.fe.specs.util.SpecsLogs; -public class CxxExpression extends AExpression { - - private final Expr expr; +public class CxxExpression> extends AExpression { public CxxExpression(Expr expr, CxxWeaver weaver) { - super(weaver); - this.expr = expr; + super(expr, weaver); } @Override - public ClavaNode getNode() { - return expr; + public Expr getNodeImpl() { + return (Expr) super.getNodeImpl(); } @Override - public AVardecl getVardeclImpl() { + public AVardecl getVardeclImpl() { // Get more specific join point for current node - - // SpecsLogs.msgInfo("attribute 'vardecl' not implemented yet for joinpoint " + getJoinPointType()); + SpecsLogs.msgInfo("attribute 'vardecl' not implemented yet for joinpoint " + getJoinPointTypeImpl()); return null; - /* - // DeclRefExpr declRefExpr = toDeclRefExpr(expr); - // if (declRefExpr == null) { - // return null; - // } - if (!(expr instanceof DeclRefExpr)) { - return null; - } - - Optional varDecl = ((DeclRefExpr) expr).getVariableDeclaration(); - // Optional varDecl = declRefExpr.getVariableDeclaration(); - - if (!varDecl.isPresent()) { - return null; - } - - return CxxJoinpoints.create(varDecl.get(), null); - */ } - /* - private DeclRefExpr toDeclRefExpr(ClavaNode node) { - if (node instanceof DeclRefExpr) { - return (DeclRefExpr) node; - } - - if (node.getNumChildren() == 1) { - return toDeclRefExpr(node.getChild(0)); - } - - return null; - } - */ - @Override - public String getUseImpl() { - return CxxAttributes.convertUse(expr.use()); - /* - switch (expr.use()) { - case READ: - return AExpressionUseEnum.READ.getName(); - case WRITE: - return AExpressionUseEnum.WRITE.getName(); - case READWRITE: - return AExpressionUseEnum.READWRITE.getName(); - default: - throw new RuntimeException("Case not defined:" + expr.use()); - } - */ + public ExpressionUse getUseImpl() { + return CxxAttributes.convertUse(this.getNodeImpl().use()); } - public static List selectVarDecl(AExpression expression) { - AVardecl vardecl = expression.getVardeclImpl(); + public static List> selectVarDecl(AExpression expression) { + AVardecl vardecl = expression.getVardeclImpl(); if (vardecl == null) { return Collections.emptyList(); } @@ -106,36 +64,37 @@ public static List selectVarDecl(AExpression expression) { } @Override - public Boolean getIsFunctionArgumentImpl() { - return expr.isFunctionArgument(); + public boolean getIsFunctionArgumentImpl() { + return this.getNodeImpl().isFunctionArgument(); } @Override - public ACast getImplicitCastImpl() { + public ACast getImplicitCastImpl() { // // Check if expr has an implicit cast // expr.hasValue(key) - return expr.getImplicitCast() + return this.getNodeImpl().getImplicitCast() .map(castExpr -> CxxJoinpoints.create(castExpr, getWeaverEngine(), ACast.class)) .orElse(null); } @Override - public ADecl getDeclImpl() { - return expr.getDecl() + public ADecl getDeclImpl() { + return this.getNodeImpl().getDecl() .map(decl -> CxxJoinpoints.create(decl, getWeaverEngine(), ADecl.class)) .orElse(null); } @Override - public AJoinPoint replaceWithImpl(AJoinPoint node) { + public AJoinpoint replaceWithImpl(AJoinpoint node) { // If node to replace is statement, check if this expression is inside an ExprStmt - if (node instanceof AStatement && node.getNode().getParent() instanceof ExprStmt) { + if (node instanceof AStatement && node.getNodeImpl().getParent() instanceof ExprStmt) { return node.getParentImpl().replaceWithImpl(node); } return super.replaceWithImpl(node); } + } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxField.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxField.java index a6ad283a9d..bd4cafa516 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxField.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxField.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.FieldDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AField; -public class CxxField extends AField { - - private final FieldDecl field; +public class CxxField> extends AField { public CxxField(FieldDecl field, CxxWeaver weaver) { - super(new CxxDeclarator(field, weaver), weaver); - this.field = field; + super(field, weaver); } @Override - public ClavaNode getNode() { - return field; + public FieldDecl getNodeImpl() { + return (FieldDecl) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFile.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFile.java index 1250f73167..e4a4bcb5cf 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFile.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFile.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.stream.Collectors; +import org.lara.interpreter.weaver.interf.enums.InsertPosition; + import pt.up.fe.specs.clava.ClavaLog; import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.Decl; @@ -34,53 +36,50 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFile; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFunction; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AInclude; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVardecl; import pt.up.fe.specs.clava.weaver.importable.AstFactory; import pt.up.fe.specs.util.SpecsIo; import pt.up.fe.specs.util.SpecsLogs; -public class CxxFile extends AFile { - - private final TranslationUnit tunit; +public class CxxFile> extends AFile { public CxxFile(TranslationUnit tunit, CxxWeaver weaver) { - super(weaver); - this.tunit = tunit; + super(tunit, weaver); + } + + @Override + public TranslationUnit getNodeImpl() { + return (TranslationUnit) super.getNodeImpl(); } @Override public String getNameImpl() { - return tunit.getFilename(); + return this.getNodeImpl().getFilename(); } @Override public void setNameImpl(String filename) { - var previousFile = tunit.get(TranslationUnit.SOURCE_FILE); + var previousFile = this.getNodeImpl().get(TranslationUnit.SOURCE_FILE); var baseFolder = previousFile != null ? previousFile.getParentFile() : null; var newFile = new File(baseFolder, filename); - tunit.set(TranslationUnit.SOURCE_FILE, newFile); - } - - @Override - public TranslationUnit getNode() { - return tunit; + this.getNodeImpl().set(TranslationUnit.SOURCE_FILE, newFile); } public TranslationUnit getTu() { - return tunit; + return this.getNodeImpl(); } @Override - public Boolean getHasMainImpl() { + public boolean getHasMainImpl() { return getFunctions().stream() .filter(function -> function.getDeclName().equals("main")) .findFirst().isPresent(); } private List getFunctions() { - return tunit.getDescendantsStream() + return this.getNodeImpl().getDescendantsStream() // FunctionDecl represents C function, C++ methods, constructors and destructors .filter(node -> node instanceof FunctionDecl) .map(function -> (FunctionDecl) function) @@ -89,139 +88,139 @@ private List getFunctions() { @Override public void addIncludeImpl(String name, boolean isAngled) { - tunit.addInclude(name, isAngled); + this.getNodeImpl().addInclude(name, isAngled); } @Override public void addCIncludeImpl(String name, boolean isAngled) { - tunit.addCInclude(name, isAngled); + this.getNodeImpl().addCInclude(name, isAngled); } @Override - public AJoinPoint[] insertImpl(String position, String code) { + public AJoinpoint[] insertImpl(InsertPosition position, String code) { var tentativeNode = getWeaverEngine().getSnippetParser().parseStmt(code); ClavaNode nodeToInsert = tentativeNode instanceof WrapperStmt ? tentativeNode.getChild(0) : getWeaverEngine().getFactory().literalDecl(code); - return CxxActions.insertAsChild(position, getNode(), nodeToInsert, getWeaverEngine()); + return CxxActions.insertAsChild(position.getDisplay(), this.getNodeImpl(), nodeToInsert, getWeaverEngine()); } @Override - public AJoinPoint insertAfterImpl(AJoinPoint node) { + public AJoinpoint insertAfterImpl(AJoinpoint node) { // Check node is a decl - if (!(node.getNode() instanceof Decl)) { + if (!(node.getNodeImpl() instanceof Decl)) { SpecsLogs.msgInfo( - "Can only insert Decl nodes in a file, tried to insert a '" + node.getJoinPointType() + "'"); + "Can only insert Decl nodes in a file, tried to insert a '" + node.getJoinPointTypeImpl() + "'"); return null; } - CxxActions.insertAsChild("after", getNode(), node.getNode(), getWeaverEngine()); + CxxActions.insertAsChild("after", this.getNodeImpl(), node.getNodeImpl(), getWeaverEngine()); return node; } @Override - public AJoinPoint insertBeforeImpl(AJoinPoint node) { + public AJoinpoint insertBeforeImpl(AJoinpoint node) { // Check node is a decl - if (node.getNode() instanceof Decl) { + if (node.getNodeImpl() instanceof Decl) { SpecsLogs.msgInfo( - "Can only insert Decl nodes in a file, tried to insert a '" + node.getJoinPointType() + "'"); + "Can only insert Decl nodes in a file, tried to insert a '" + node.getJoinPointTypeImpl() + "'"); return null; } - CxxActions.insertAsChild("before", getNode(), node.getNode(), getWeaverEngine()); + CxxActions.insertAsChild("before", this.getNodeImpl(), node.getNodeImpl(), getWeaverEngine()); return node; } @Override public String getPathImpl() { - return tunit.getFolderpath().orElse(null); + return this.getNodeImpl().getFolderpath().orElse(null); } @Override - public void addIncludeJpImpl(AJoinPoint jp) { + public void addIncludeJpImpl(AJoinpoint jp) { // If jp is a function, include declaration if available - if (jp.instanceOf("function")) { - AFunction functionJp = (AFunction) jp; - AJoinPoint decl = functionJp.getDeclarationJpImpl(); + if (jp.getInstanceOfImpl("function")) { + AFunction functionJp = (AFunction) jp; + AJoinpoint decl = functionJp.getDeclarationJpImpl(); jp = decl != null ? decl : jp; } // Get first joinpoint that is a CxxFile - CxxFile includeFile = CxxJoinpoints.getAncestorandSelf(jp, CxxFile.class).get(); + CxxFile includeFile = CxxJoinpoints.getAncestorandSelf(jp, CxxFile.class).get(); // If file is the same as the current file, ignore - if (includeFile.tunit.getLocation().equals(tunit.getLocation())) { - ClavaLog.debug("addIncludeJp: ignoring include '" + includeFile.getNode().getRelativeFilepath() + if (includeFile.getNodeImpl().getLocation().equals(this.getNodeImpl().getLocation())) { + ClavaLog.debug("addIncludeJp: ignoring include '" + includeFile.getNodeImpl().getRelativeFilepath() + "', since it is in the same file"); return; } - if (!includeFile.tunit.isHeaderFile()) { - ClavaLog.info("addIncludeJp: not adding file '" + includeFile.getNode().getRelativeFilepath() + if (!includeFile.getNodeImpl().isHeaderFile()) { + ClavaLog.info("addIncludeJp: not adding file '" + includeFile.getNodeImpl().getRelativeFilepath() + "' as an include, since it is not a header file"); return; } - String includePath = includeFile.getNode().getRelativeFilepath(); + String includePath = includeFile.getNodeImpl().getRelativeFilepath(); - tunit.addInclude(includePath, false); + this.getNodeImpl().addInclude(includePath, false); } @Override public String getFilepathImpl() { - return tunit.getFile().getPath(); + return this.getNodeImpl().getFile().getPath(); } @Override public String getRelativeFolderpathImpl() { - return tunit.getRelativeFolderpath().orElse(null); + return this.getNodeImpl().getRelativeFolderpath().orElse(null); } @Override public void setRelativeFolderpathImpl(String path) { - tunit.setRelativePath(path); + this.getNodeImpl().setRelativePath(path); } @Override public String getRelativeFilepathImpl() { - return tunit.getRelativeFilepath(); + return this.getNodeImpl().getRelativeFilepath(); } @Override - public Boolean getIsCxxImpl() { - return tunit.isCXXUnit(); + public boolean getIsCxxImpl() { + return this.getNodeImpl().isCXXUnit(); } @Override - public AVardecl addGlobalImpl(String name, AJoinPoint type, String initValue) { + public AVardecl addGlobalImpl(String name, AJoinpoint type, String initValue) { // Check if joinpoint is a CxxType if (!(type instanceof AType)) { - SpecsLogs.msgInfo("addGlobal: the provided join point (" + type.getJoinPointType() + ") is not a type"); + SpecsLogs.msgInfo("addGlobal: the provided join point (" + type.getJoinPointTypeImpl() + ") is not a type"); return null; } - Type typeNode = (Type) type.getNode(); + Type typeNode = (Type) type.getNodeImpl(); LiteralExpr literalExpr = getWeaverEngine().getFactory().literalExpr(initValue, typeNode); - VarDecl global = tunit.getApp().getGlobalManager().addGlobal(tunit, name, typeNode, literalExpr); + VarDecl global = this.getNodeImpl().getApp().getGlobalManager().addGlobal(this.getNodeImpl(), name, typeNode, literalExpr); return CxxJoinpoints.create(global, getWeaverEngine(), AVardecl.class); } @Override - public void insertBeginImpl(AJoinPoint node) { - if (!tunit.hasChildren()) { - tunit.addChild(node.getNode()); + public void insertBeginImpl(AJoinpoint node) { + if (!this.getNodeImpl().hasChildren()) { + this.getNodeImpl().addChild(node.getNodeImpl()); return; } - tunit.addChild(0, node.getNode()); + this.getNodeImpl().addChild(0, node.getNodeImpl()); } @Override @@ -230,13 +229,13 @@ public void insertBeginImpl(String code) { } @Override - public void insertEndImpl(AJoinPoint node) { - if (!tunit.hasChildren()) { - tunit.addChild(node.getNode()); + public void insertEndImpl(AJoinpoint node) { + if (!this.getNodeImpl().hasChildren()) { + this.getNodeImpl().addChild(node.getNodeImpl()); return; } - tunit.addChild(node.getNode()); + this.getNodeImpl().addChild(node.getNodeImpl()); } @Override @@ -245,18 +244,18 @@ public void insertEndImpl(String code) { } @Override - public AJoinPoint addFunctionImpl(String name) { - CxxFunction function = AstFactory.functionVoid(getWeaverEngine(), name); + public AJoinpoint addFunctionImpl(String name) { + CxxFunction function = AstFactory.functionVoid(getWeaverEngine(), name); // Add function to the tree - tunit.addChild(function.getNode()); + this.getNodeImpl().addChild(function.getNodeImpl()); return function; } @Override - public Boolean getIsHeaderImpl() { - return tunit.isHeaderFile(); + public boolean getIsHeaderImpl() { + return this.getNodeImpl().isHeaderFile(); } @Override @@ -267,31 +266,31 @@ public String writeImpl(String destinationFoldername) { return null; } - File writtenFile = tunit.write(destinationFolder); + File writtenFile = this.getNodeImpl().write(destinationFolder); getWeaverEngine().getWeaverData().addManualWrittenFile(writtenFile); return writtenFile.getAbsolutePath(); } @Override - public Boolean getIsOpenCLImpl() { - return tunit.isOpenCLFile(); + public boolean getIsOpenCLImpl() { + return this.getNodeImpl().isOpenCLFile(); } @Override - public AInclude[] getIncludesArrayImpl() { - return CxxSelects.select(getWeaverEngine(), AInclude.class, tunit.getChildren(), false, IncludeDecl.class).toArray(size -> new AInclude[size]); + public AInclude[] getIncludesImpl() { + return CxxSelects.select(getWeaverEngine(), AInclude.class, this.getNodeImpl().getChildren(), false, IncludeDecl.class); } @Override public String getBaseSourcePathImpl() { SpecsLogs.warn( "Attribute $file.baseSourcePath is deprecated, please use attribute $file.relativeFolderpath, which returns the same."); - return tunit.getRelativeFolderpath().orElse(null); + return this.getNodeImpl().getRelativeFolderpath().orElse(null); } @Override - public String getDestinationFilepathImpl(String destinationFolderpath) { + public String getGetDestinationFilepathImpl(String destinationFolderpath) { File file; if (destinationFolderpath == "" ) { @@ -299,47 +298,37 @@ public String getDestinationFilepathImpl(String destinationFolderpath) { } else { file = new File(destinationFolderpath); } - - return tunit.getDestinationFile(file).getAbsolutePath(); + + return this.getNodeImpl().getDestinationFile(file).getAbsolutePath(); } @Override - public AFile rebuildImpl() { - TranslationUnit rebuiltTunit = getWeaverEngine().rebuildFile(tunit); + public AFile rebuildImpl() { + TranslationUnit rebuiltTunit = getWeaverEngine().rebuildFile(this.getNodeImpl()); - AFile rebuiltFile = CxxJoinpoints.create(rebuiltTunit, getWeaverEngine(), AFile.class); - replaceWith(rebuiltFile); + AFile rebuiltFile = CxxJoinpoints.create(rebuiltTunit, getWeaverEngine(), AFile.class); + replaceWithImpl(rebuiltFile); return rebuiltFile; } - @Override - public AJoinPoint rebuildTryImpl() { - try { - return rebuildImpl(); - } catch (Exception e) { - System.out.println("EXCEPTION: " + e); - return new CxxClavaException(e, getWeaverEngine()); - } - } - @Override public Object getFileImpl() { - return tunit.getFile(); + return this.getNodeImpl().getFile(); } @Override public String getSourceFoldernameImpl() { - return tunit.get(TranslationUnit.SOURCE_FOLDERNAME).orElse(null); + return this.getNodeImpl().get(TranslationUnit.SOURCE_FOLDERNAME).orElse(null); } @Override - public Boolean getHasParsingErrorsImpl() { - return tunit.get(TranslationUnit.HAS_PARSING_ERRORS); + public boolean getHasParsingErrorsImpl() { + return this.getNodeImpl().get(TranslationUnit.HAS_PARSING_ERRORS); } @Override public String getErrorOutputImpl() { - return tunit.get(TranslationUnit.ERROR_OUTPUT); + return this.getNodeImpl().get(TranslationUnit.ERROR_OUTPUT); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFloatLiteral.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFloatLiteral.java index 0905a7eb1d..7718dace3e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFloatLiteral.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFloatLiteral.java @@ -13,29 +13,24 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.FloatingLiteral; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFloatLiteral; -public class CxxFloatLiteral extends AFloatLiteral { - - private final FloatingLiteral literal; +public class CxxFloatLiteral> extends AFloatLiteral { public CxxFloatLiteral(FloatingLiteral literal, CxxWeaver weaver) { - super(new CxxLiteral(literal, weaver), weaver); - - this.literal = literal; + super(literal, weaver); } @Override - public ClavaNode getNode() { - return literal; + public FloatingLiteral getNodeImpl() { + return (FloatingLiteral) super.getNodeImpl(); } @Override - public Double getValueImpl() { - return literal.get(FloatingLiteral.VALUE).doubleValue(); + public double getValueImpl() { + return this.getNodeImpl().get(FloatingLiteral.VALUE).doubleValue(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFunction.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFunction.java index 6e76ffc89b..7319758734 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFunction.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxFunction.java @@ -13,12 +13,23 @@ package pt.up.fe.specs.clava.weaver.joinpoints; +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.lara.interpreter.weaver.interf.enums.InsertPosition; + import pt.up.fe.specs.clava.ClavaLog; import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaNodes; import pt.up.fe.specs.clava.ast.attr.CUDAGlobalAttr; -import pt.up.fe.specs.clava.ast.decl.*; -import pt.up.fe.specs.clava.ast.decl.enums.StorageClass; +import pt.up.fe.specs.clava.ast.decl.FunctionDecl; +import pt.up.fe.specs.clava.ast.decl.IncludeDecl; +import pt.up.fe.specs.clava.ast.decl.ParmVarDecl; +import pt.up.fe.specs.clava.ast.decl.VarDecl; import pt.up.fe.specs.clava.ast.expr.Expr; import pt.up.fe.specs.clava.ast.extra.App; import pt.up.fe.specs.clava.ast.extra.TranslationUnit; @@ -29,66 +40,86 @@ import pt.up.fe.specs.clava.weaver.CxxActions; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.*; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ABody; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ACall; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFile; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFunction; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFunctionType; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AParam; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AScope; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; +import pt.up.fe.specs.clava.weaver.enums.StorageClass; import pt.up.fe.specs.clava.weaver.importable.AstFactory; import pt.up.fe.specs.util.SpecsCollections; import pt.up.fe.specs.util.SpecsIo; import pt.up.fe.specs.util.SpecsLogs; +import pt.up.fe.specs.util.lazy.Lazy; +import pt.up.fe.specs.util.lazy.ThreadSafeLazy; import pt.up.fe.specs.util.treenode.NodeInsertUtils; import pt.up.fe.specs.util.treenode.TreeNodeUtils; -import java.io.File; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; +public class CxxFunction> extends AFunction { + + private static final Lazy> STORAGE_TYPE = new ThreadSafeLazy<>( + () -> buildStorageTypeMap()); + + private static Map buildStorageTypeMap() { + HashMap storageClasses = new HashMap<>(); -public class CxxFunction extends AFunction { - private final FunctionDecl function; + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.None, StorageClass.NONE); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Extern, StorageClass.EXTERN); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Static, StorageClass.STATIC); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.PrivateExtern, StorageClass.PRIVATE_EXTERN); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Auto, StorageClass.AUTO); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Register, StorageClass.REGISTER); + + return storageClasses; + } public CxxFunction(FunctionDecl function, CxxWeaver weaver) { - super(new CxxDeclarator(function, weaver), weaver); - this.function = function; + super(function, weaver); } @Override - public FunctionDecl getNode() { - return function; + public FunctionDecl getNodeImpl() { + return (FunctionDecl) super.getNodeImpl(); } @Override - public AType getTypeImpl() { - return CxxJoinpoints.create(function.getReturnType(), getWeaverEngine(), AType.class); + public AType getTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getReturnType(), getWeaverEngine(), AType.class); } @Override - public AFunctionType getFunctionTypeImpl() { - return CxxJoinpoints.create(function.getFunctionType(), getWeaverEngine(), AFunctionType.class); + public AFunctionType getFunctionTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getFunctionType(), getWeaverEngine(), AFunctionType.class); } @Override - public ACall newCallImpl(AJoinPoint[] args) { - return AstFactory.callFromFunction(getWeaverEngine(), this, SpecsCollections.asListT(AJoinPoint.class, (Object[]) args)); + public ACall newCallImpl(AJoinpoint[] args) { + return AstFactory.callFromFunction(getWeaverEngine(), this, SpecsCollections.asListT(AJoinpoint.class, (Object[]) args)); } @Override - public Boolean getHasDefinitionImpl() { + public boolean getHasDefinitionImpl() { return getIsImplementationImpl(); } @Override - public Boolean getIsImplementationImpl() { - return function.hasBody(); + public boolean getIsImplementationImpl() { + return this.getNodeImpl().hasBody(); } @Override - public Boolean getIsPrototypeImpl() { - return !function.hasBody(); + public boolean getIsPrototypeImpl() { + return !this.getNodeImpl().hasBody(); } - private AJoinPoint processNodeToInsert(AJoinPoint node) { + private AJoinpoint processNodeToInsert(AJoinpoint node) { // If node is an expression or VarDecl, convert to Stmt first - var clavaNode = node.getNode(); + var clavaNode = node.getNodeImpl(); if (clavaNode instanceof VarDecl || clavaNode instanceof Expr) { return CxxJoinpoints.create(ClavaNodes.toStmt(clavaNode), getWeaverEngine()); @@ -99,88 +130,87 @@ private AJoinPoint processNodeToInsert(AJoinPoint node) { } @Override - public AJoinPoint[] insertImpl(String position, String code) { + public AJoinpoint[] insertImpl(InsertPosition position, String code) { // Stmt literalStmt = ClavaNodeFactory.literalStmt(code); Stmt literalStmt = getWeaverEngine().getSnippetParser().parseStmt(code); return insertStmt(literalStmt, position); } @Override - public AJoinPoint insertAfterImpl(AJoinPoint node) { + public AJoinpoint insertAfterImpl(AJoinpoint node) { var processNode = processNodeToInsert(node); return CxxActions.insertJp(this, processNode, "after", getWeaverEngine()); } @Override - public AJoinPoint insertAfterImpl(String code) { + public AJoinpoint insertAfterImpl(String code) { return insertAfterImpl(CxxJoinpoints.create(getWeaverEngine().getSnippetParser().parseStmt(code), getWeaverEngine())); } @Override - public AJoinPoint insertBeforeImpl(AJoinPoint node) { + public AJoinpoint insertBeforeImpl(AJoinpoint node) { var processNode = processNodeToInsert(node); return CxxActions.insertJp(this, processNode, "before", getWeaverEngine()); } @Override - public AJoinPoint insertBeforeImpl(String code) { + public AJoinpoint insertBeforeImpl(String code) { return insertBeforeImpl(CxxJoinpoints.create(getWeaverEngine().getSnippetParser().parseStmt(code), getWeaverEngine())); } @Override - public AJoinPoint replaceWithImpl(AJoinPoint node) { + public AJoinpoint replaceWithImpl(AJoinpoint node) { var processNode = processNodeToInsert(node); return CxxActions.insertJp(this, processNode, "replace", getWeaverEngine()); } - private AJoinPoint[] insertStmt(Stmt newNode, String position) { + private AJoinpoint[] insertStmt(Stmt newNode, InsertPosition position) { switch (position) { - case "before": - NodeInsertUtils.insertBefore(function, newNode); + case BEFORE: + NodeInsertUtils.insertBefore(this.getNodeImpl(), newNode); return null; - case "after": - NodeInsertUtils.insertAfter(function, newNode); + case AFTER: + NodeInsertUtils.insertAfter(this.getNodeImpl(), newNode); return null; - case "around": - case "replace": - NodeInsertUtils.replace(function, newNode); - return new AJoinPoint[]{CxxJoinpoints.create(newNode, getWeaverEngine())}; + case REPLACE: + NodeInsertUtils.replace(this.getNodeImpl(), newNode); + return new AJoinpoint[]{CxxJoinpoints.create(newNode, getWeaverEngine())}; default: throw new RuntimeException("Case not defined:" + position); } } @Override - public String getDeclarationImpl(Boolean withReturnType) { - return function.getDeclarationId(withReturnType); + public String getGetDeclarationImpl(boolean withReturnType) { + return this.getNodeImpl().getDeclarationId(withReturnType); } @Override - public ABody getBodyImpl() { - if (!function.hasBody()) { + public ABody getBodyImpl() { + if (!this.getNodeImpl().hasBody()) { return null; } - return CxxJoinpoints.create(function.getBody().get(), getWeaverEngine(), ABody.class); + return CxxJoinpoints.create(this.getNodeImpl().getBody().get(), getWeaverEngine(), ABody.class); } @Override - public AFunction cloneImpl(String newName, Boolean insert) { + public AFunction cloneImpl(String newName, boolean insert) { /* make clone and insert after the function of this join point */ - return makeCloneAndInsert(newName, function, insert); + return makeCloneAndInsert(newName, this.getNodeImpl(), insert); } - private AFunction makeCloneAndInsert(String newName, ClavaNode reference, boolean insert) { + private AFunction makeCloneAndInsert(String newName, ClavaNode reference, boolean insert) { FunctionDecl newFunc = null; if (reference instanceof FunctionDecl) { - newFunc = function.cloneAndInsert(newName, insert); + newFunc = this.getNodeImpl().cloneAndInsert(newName, insert); } else if (reference instanceof TranslationUnit) { - newFunc = function.cloneAndInsertOnFile(newName, (TranslationUnit) reference, insert); + newFunc = this.getNodeImpl().cloneAndInsertOnFile(newName, (TranslationUnit) reference, insert); } else { throw new IllegalArgumentException( "The node (" + reference + ") needs to be either a FuncDecl or a TranslationUnit."); @@ -190,9 +220,9 @@ private AFunction makeCloneAndInsert(String newName, ClavaNode reference, boolea } @Override - public AFunction cloneOnFileImpl(String newName, String fileName) { + public AFunction cloneOnFileImpl(String newName, String fileName) { if (fileName == null) { - boolean isCxx = function.getAncestor(TranslationUnit.class).isCXXUnit(); + boolean isCxx = this.getNodeImpl().getAncestor(TranslationUnit.class).isCXXUnit(); String extension = getIsPrototypeImpl() ? ".h" : isCxx ? ".cpp" : ".c"; String prefix = newName; @@ -202,7 +232,7 @@ public AFunction cloneOnFileImpl(String newName, String fileName) { // First, check if the given filename is the same as a file in the AST - App app = (App) getRootImpl().getNode(); + App app = (App) getRootImpl().getNodeImpl(); var currentFile = new File(fileName); var existingFile = app.getTranslationUnits().stream() @@ -210,7 +240,7 @@ public AFunction cloneOnFileImpl(String newName, String fileName) { .findFirst(); if (existingFile.isPresent()) { - return cloneOnFileImpl(newName, new CxxFile(existingFile.get(), getWeaverEngine())); + return cloneOnFileImpl(newName, new CxxFile<>(existingFile.get(), getWeaverEngine())); } // Extract relative path @@ -220,54 +250,27 @@ public AFunction cloneOnFileImpl(String newName, String fileName) { var newFile = AstFactory.file(getWeaverEngine(), fileName, relativePath); // Set same source foldername - var originalFile = function.getAncestorTry(TranslationUnit.class).orElse(null); + var originalFile = this.getNodeImpl().getAncestorTry(TranslationUnit.class).orElse(null); if (originalFile != null) { - // newFile.getNode().set(TranslationUnit.SOURCE_FOLDERNAME, - // originalFile.get(TranslationUnit.SOURCE_FOLDERNAME)); - newFile.getNode().copyValue(TranslationUnit.SOURCE_FOLDERNAME, originalFile); - // originalFile.get(TranslationUnit.SOURCE_FOLDERNAME). + newFile.getNodeImpl().copyValue(TranslationUnit.SOURCE_FOLDERNAME, originalFile); } - // System.out.println("NEW FILE:" + newFile.getNode()); - // System.out.println("CURRRENT FILE:" + function.getAncestor(TranslationUnit.class)); - app.addFile((TranslationUnit) newFile.getNode()); + app.addFile((TranslationUnit) newFile.getNodeImpl()); return cloneOnFileImpl(newName, newFile); } @Override // TODO: copy header file inclusion - public AFunction cloneOnFileImpl(String newName, AFile file) { - - // if (!function.hasBody()) { - // /*add the clone to the original place in order to be included where needed */ - // return makeCloneAndInsert(newName, function, true); - // } - - /* if this is a definition, add the clone to the correct file */ - - // App app = getRootImpl().getNode(); - // - // Optional file = app.getFile(fileName); - // - // if (!file.isPresent()) { - // - // TranslationUnit tu = getFactory().translationUnit(new File(fileName), Collections.emptyList()); - // - // app.addFile(tu); - // - // file = Optional.of(tu); - // } - - var tu = (TranslationUnit) file.getNode(); + public AFunction cloneOnFileImpl(String newName, AFile file) { + var tu = (TranslationUnit) file.getNodeImpl(); var cloneFunction = makeCloneAndInsert(newName, tu, true); /* copy headers from the current file to the file with the clone */ - TranslationUnit originalFile = function.getAncestorTry(TranslationUnit.class).orElse(null); + TranslationUnit originalFile = this.getNodeImpl().getAncestorTry(TranslationUnit.class).orElse(null); if (originalFile != null) { var includesCopy = TreeNodeUtils.copy(originalFile.getIncludes().getIncludes()); - // List allIncludes = getIncludesCopyFromFile(originalFile); File baseIncludePath = null; @@ -284,9 +287,6 @@ public AFunction cloneOnFileImpl(String newName, AFile file) { .map(relativeFolder -> new File(relativeDepth, relativeFolder)) .orElse(baseIncludePath); - // System.out.println("BASE: " + baseIncludePath); - // System.out.println("DEPTH: " + relativeFolderDepth); - // Adapt includes for (var includeDecl : includesCopy) { var include = includeDecl.getInclude(); @@ -295,10 +295,9 @@ public AFunction cloneOnFileImpl(String newName, AFile file) { if (include.isAngled()) { continue; } - // System.out.println("INCLUDE BEFORE: " + includeDecl.getCode()); + var newInclude = include.setInclude(new File(baseIncludePath, include.getInclude()).toString()); includeDecl.set(IncludeDecl.INCLUDE, newInclude); - // System.out.println("INCLUDE AFTER: " + includeDecl.getCode()); } // Add includes @@ -310,9 +309,8 @@ public AFunction cloneOnFileImpl(String newName, AFile file) { } @Override - public String[] getParamNamesArrayImpl() { - - return function.getParameters() + public String[] getParamNamesImpl() { + return this.getNodeImpl().getParameters() .stream() .map(ParmVarDecl::getCode) .collect(Collectors.toList()) @@ -320,8 +318,8 @@ public String[] getParamNamesArrayImpl() { } @Override - public AParam[] getParamsArrayImpl() { - return function.getParameters() + public AParam[] getParamsImpl() { + return this.getNodeImpl().getParameters() .stream() .map(param -> CxxJoinpoints.create(param, getWeaverEngine(), AParam.class)) @@ -330,58 +328,23 @@ public AParam[] getParamsArrayImpl() { } @Override - public AJoinPoint insertReturnImpl(String code) { + public AJoinpoint insertReturnImpl(String code) { return insertReturnImpl(CxxJoinpoints.create(getWeaverEngine().getSnippetParser().parseStmt(code), getWeaverEngine())); } @Override - public AJoinPoint insertReturnImpl(AJoinPoint code) { + public AJoinpoint insertReturnImpl(AJoinpoint code) { // Does not take into account situations where functions returns in all paths of an if/else. // This means it can lead to dead-code, although for C/C++ that does not seem to be problematic. // Do not insert if function has no implementation - if (!function.hasBody()) { + if (!this.getNodeImpl().hasBody()) { ClavaLog.info("insertReturn: could not insert in function without body"); return null; } return CxxActions.insertReturn(getBodyImpl(), code, getWeaverEngine()); - - // - // List bodyStmts = function.getBody().get().toStatements(); - // - // // Check if it has return statement, ignoring wrapper statements - // Stmt lastStmt = SpecsCollections.reverseStream(bodyStmts) - // .filter(stmt -> !(stmt instanceof WrapperStmt)) - // .findFirst().orElse(null); - // - // ReturnStmt lastReturnStmt = lastStmt instanceof ReturnStmt ? (ReturnStmt) lastStmt : null; - // - // // Get list of all return statements inside children - // List returnStatements = bodyStmts.stream() - // .flatMap(Stmt::getDescendantsStream) - // .filter(ReturnStmt.class::isInstance) - // .map(ReturnStmt.class::cast) - // .collect(Collectors.toList()); - // - // AJoinPoint lastInsertPoint = null; - // - // if (lastReturnStmt != null) { - // returnStatements = SpecsCollections.concat(returnStatements, lastReturnStmt); - // } - // - // for (ReturnStmt returnStmt : returnStatements) { - // ACxxWeaverJoinPoint returnJp = CxxJoinpoints.create(returnStmt); - // lastInsertPoint = returnJp.insertBefore(code); - // } - // - // // If there is no return in the body, add at the end of the function - // if (lastReturnStmt == null) { - // lastInsertPoint = getBodyImpl().insertEnd(code); - // } - // - // return lastInsertPoint; } /** @@ -389,19 +352,19 @@ public AJoinPoint insertReturnImpl(AJoinPoint code) { */ @Override public String getIdImpl() { - return getDeclarationImpl(false); + return getGetDeclarationImpl(false); } @Override - public AFunction[] getDeclarationJpsArrayImpl() { - return function.getPrototypes().stream() + public AFunction[] getDeclarationJpsImpl() { + return this.getNodeImpl().getPrototypes().stream() .map(node -> CxxJoinpoints.create(node, getWeaverEngine(), AFunction.class)) - .toArray(size -> new AFunction[size]); + .toArray(AFunction[]::new); } @Override - public AFunction getDeclarationJpImpl() { - var prototypes = getDeclarationJpsArrayImpl(); + public AFunction getDeclarationJpImpl() { + var prototypes = getDeclarationJpsImpl(); if (prototypes.length == 0) { return null; @@ -416,8 +379,8 @@ public AFunction getDeclarationJpImpl() { } @Override - public AFunction getDefinitionJpImpl() { - return function.getImplementation() + public AFunction getDefinitionJpImpl() { + return this.getNodeImpl().getImplementation() .map(node -> CxxJoinpoints.create(node, getWeaverEngine(), AFunction.class)) .orElse(null); } @@ -426,7 +389,7 @@ public AFunction getDefinitionJpImpl() { * Setting the type of a Function join point sets the return type */ @Override - public void setTypeImpl(AType type) { + public void setTypeImpl(AType type) { setReturnTypeImpl(type); } @@ -436,77 +399,92 @@ public void setNameImpl(String name) { // Needs to first fetch both definition and declaration. // If one is renamed before fetching the other, the other will not be found - var impl = function.getImplementation(); - var proto = function.getPrototypes(); + var impl = this.getNodeImpl().getImplementation(); + var proto = this.getNodeImpl().getPrototypes(); impl.ifPresent(node -> node.setName(name)); proto.stream().forEach(node -> node.setName(name)); } @Override - public String getStorageClassImpl() { - return function.get(FunctionDecl.STORAGE_CLASS).getString(); + public StorageClass getStorageClassImpl() { + var nodeStorageClass = this.getNodeImpl().get(FunctionDecl.STORAGE_CLASS); + if (nodeStorageClass == null) { + throw new RuntimeException("Storage class of function '" + getSignatureImpl() + "' is null"); + } + + StorageClass jpStorageClass = STORAGE_TYPE.get().get(nodeStorageClass); + if (jpStorageClass == null) { + throw new RuntimeException("Storage class '" + nodeStorageClass + "' of function '" + getSignatureImpl() + + "' is not supported in the join point model"); + } + + return jpStorageClass; } @Override - public boolean setStorageClassImpl(String storageClass) { - // Get corresponding enum - var storageClassEnum = StorageClass.getHelper().fromValue(storageClass); + public boolean setStorageClassImpl(StorageClass storageClass) { + var nodeStorageClass = STORAGE_TYPE.get().entrySet().stream() + .filter(entry -> entry.getValue() == storageClass) + .map(Map.Entry::getKey) + .findFirst() + .orElseThrow(() -> new RuntimeException( + "Storage class '" + storageClass + "' is not supported in the join point model")); - return function.setStorageClass(storageClassEnum); + return this.getNodeImpl().setStorageClass(nodeStorageClass); } @Override - public Boolean getIsInlineImpl() { - return function.get(FunctionDecl.IS_INLINE_SPECIFIED); + public boolean getIsInlineImpl() { + return this.getNodeImpl().get(FunctionDecl.IS_INLINE_SPECIFIED); } @Override - public Boolean getIsVirtualImpl() { - return function.get(FunctionDecl.IS_VIRTUAL_AS_WRITTEN); + public boolean getIsVirtualImpl() { + return this.getNodeImpl().get(FunctionDecl.IS_VIRTUAL_AS_WRITTEN); } @Override - public Boolean getIsModulePrivateImpl() { - return function.get(FunctionDecl.IS_MODULE_PRIVATE); + public boolean getIsModulePrivateImpl() { + return this.getNodeImpl().get(FunctionDecl.IS_MODULE_PRIVATE); } @Override - public Boolean getIsPureImpl() { - return function.get(FunctionDecl.IS_PURE); + public boolean getIsPureImpl() { + return this.getNodeImpl().get(FunctionDecl.IS_PURE); } @Override - public Boolean getIsDeleteImpl() { - return function.get(FunctionDecl.IS_DELETED); + public boolean getIsDeleteImpl() { + return this.getNodeImpl().get(FunctionDecl.IS_DELETED); } @Override - public ACall[] getCallsArrayImpl() { - return function.getCalls().stream() + public ACall[] getCallsImpl() { + return this.getNodeImpl().getCalls().stream() .map(call -> CxxJoinpoints.create(call, getWeaverEngine(), ACall.class)) .toArray(ACall[]::new); } @Override - public void setParamsImpl(AParam[] params) { + public void setParamsImpl(AParam[] params) { List newParams = Arrays.stream( params) - .map(param -> (ParmVarDecl) param.getNode()) + .map(param -> (ParmVarDecl) param.getNodeImpl()) .collect(Collectors.toList()); - function.setParameters(newParams); + this.getNodeImpl().setParameters(newParams); } @Override public void setParamsFromStringsImpl(String[] params) { - AParam[] newParams = new AParam[params.length]; + AParam[] newParams = new AParam[params.length]; // Each value is a type - varName pair, separate them by last space for (int i = 0; i < params.length; i++) { String typeVarname = params[i]; - var parmVarDecl = ClavaNodes.toParam(typeVarname, function); + var parmVarDecl = ClavaNodes.toParam(typeVarname, this.getNodeImpl()); newParams[i] = CxxJoinpoints.create(parmVarDecl, getWeaverEngine(), AParam.class); } @@ -516,37 +494,37 @@ public void setParamsFromStringsImpl(String[] params) { @Override public String getSignatureImpl() { - return function.getSignature(); + return this.getNodeImpl().getSignature(); } @Override - public void setBodyImpl(AScope body) { - function.setBody((CompoundStmt) body.getNode()); + public void setBodyImpl(AScope body) { + this.getNodeImpl().setBody((CompoundStmt) body.getNodeImpl()); } @Override - public void setFunctionTypeImpl(AFunctionType functionType) { - function.setFunctionType((FunctionType) functionType.getNode()); + public void setFunctionTypeImpl(AFunctionType functionType) { + this.getNodeImpl().setFunctionType((FunctionType) functionType.getNodeImpl()); } @Override - public AType getReturnTypeImpl() { - return CxxJoinpoints.create(function.getReturnType(), getWeaverEngine(), AType.class); + public AType getReturnTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getReturnType(), getWeaverEngine(), AType.class); } @Override - public void setReturnTypeImpl(AType returnType) { - function.setReturnType((Type) returnType.getNode()); + public void setReturnTypeImpl(AType returnType) { + this.getNodeImpl().setReturnType((Type) returnType.getNodeImpl()); } @Override - public void setParamTypeImpl(int index, AType newType) { - function.setParamType(index, (Type) newType.getNode()); + public void setParamTypeImpl(int index, AType newType) { + this.getNodeImpl().setParamType(index, (Type) newType.getNodeImpl()); } @Override - public void addParamImpl(AParam param) { - var originalParams = getParamsArrayImpl(); + public void addParamImpl(AParam param) { + var originalParams = getParamsImpl(); var newParams = Arrays.copyOf(originalParams, originalParams.length + 1); newParams[newParams.length - 1] = param; @@ -555,23 +533,23 @@ public void addParamImpl(AParam param) { } @Override - public void addParamImpl(String name, AType type) { + public void addParamImpl(String name, AType type) { ClavaNode paramNode; if (type == null) { - paramNode = ClavaNodes.toParam(name, function); + paramNode = ClavaNodes.toParam(name, this.getNodeImpl()); } else { - paramNode = getFactory().parmVarDecl(name, (Type) type.getNode()); + paramNode = getFactory().parmVarDecl(name, (Type) type.getNodeImpl()); } addParamImpl(CxxJoinpoints.create(paramNode, getWeaverEngine(), AParam.class)); } @Override - public void setParamImpl(int index, AParam param) { - var params = getParamsArrayImpl(); + public void setParamImpl(int index, AParam param) { + var params = getParamsImpl(); if (index >= params.length) { SpecsLogs.info("Tried to set parameter '" + param.getCodeImpl() + "' at index '" + index - + "' but function '" + function.getSignature() + "' only has " + params.length + " parameters"); + + "' but function '" + this.getNodeImpl().getSignature() + "' only has " + params.length + " parameters"); return; } @@ -581,34 +559,34 @@ public void setParamImpl(int index, AParam param) { } @Override - public void setParamImpl(int index, String name, AType type) { + public void setParamImpl(int index, String name, AType type) { ClavaNode paramNode; if (type == null) { - paramNode = ClavaNodes.toParam(name, function); + paramNode = ClavaNodes.toParam(name, this.getNodeImpl()); } else { - paramNode = getFactory().parmVarDecl(name, (Type) type.getNode()); + paramNode = getFactory().parmVarDecl(name, (Type) type.getNodeImpl()); } setParamImpl(index, CxxJoinpoints.create(paramNode, getWeaverEngine(), AParam.class)); } @Override - public Boolean getIsCudaKernelImpl() { - return function.get(FunctionDecl.ATTRIBUTES).stream() + public boolean getIsCudaKernelImpl() { + return this.getNodeImpl().get(FunctionDecl.ATTRIBUTES).stream() .filter(attr -> attr instanceof CUDAGlobalAttr) .findFirst() .isPresent(); } @Override - public AFunction getCanonicalImpl() { - return CxxJoinpoints.create(function.canonical(), getWeaverEngine(), AFunction.class); + public AFunction getCanonicalImpl() { + return CxxJoinpoints.create(this.getNodeImpl().canonical(), getWeaverEngine(), AFunction.class); } @Override - public Boolean getIsCanonicalImpl() { - return function.isCanonical(); + public boolean getIsCanonicalImpl() { + return this.getNodeImpl().isCanonical(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxGotoStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxGotoStmt.java index b6e191a330..49514056f0 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxGotoStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxGotoStmt.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.LabelDecl; import pt.up.fe.specs.clava.ast.stmt.GotoStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,29 +20,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AGotoStmt; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ALabelDecl; -public class CxxGotoStmt extends AGotoStmt { - - private final GotoStmt gotoStmt; +public class CxxGotoStmt> extends AGotoStmt { public CxxGotoStmt(GotoStmt gotoStmt, CxxWeaver weaver) { - super(new CxxStatement(gotoStmt, weaver), weaver); - - this.gotoStmt = gotoStmt; + super(gotoStmt, weaver); } @Override - public ClavaNode getNode() { - return gotoStmt; + public GotoStmt getNodeImpl() { + return (GotoStmt) super.getNodeImpl(); } @Override - public void setLabelImpl(ALabelDecl label) { - gotoStmt.setLabel((LabelDecl) label.getNode()); + public void setLabelImpl(ALabelDecl label) { + this.getNodeImpl().setLabel((LabelDecl) label.getNodeImpl()); } @Override - public ALabelDecl getLabelImpl() { - return CxxJoinpoints.create(gotoStmt.getLabel(), getWeaverEngine(), ALabelDecl.class); + public ALabelDecl getLabelImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getLabel(), getWeaverEngine(), ALabelDecl.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIf.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIf.java index a632ca3bc8..ba625e6760 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIf.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIf.java @@ -18,7 +18,6 @@ import java.util.List; import java.util.stream.Collectors; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.Expr; import pt.up.fe.specs.clava.ast.stmt.IfStmt; import pt.up.fe.specs.clava.ast.stmt.Stmt; @@ -31,66 +30,63 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVardecl; import pt.up.fe.specs.util.SpecsCollections; -public class CxxIf extends AIf { - - private final IfStmt ifStmt; +public class CxxIf> extends AIf { public CxxIf(IfStmt ifStmt, CxxWeaver weaver) { - super(new CxxStatement(ifStmt, weaver), weaver); - this.ifStmt = ifStmt; + super(ifStmt, weaver); } @Override - public ClavaNode getNode() { - return ifStmt; + public IfStmt getNodeImpl() { + return (IfStmt) super.getNodeImpl(); } @Override - public AExpression getCondImpl() { - List list = Collections.emptyList(); + public AExpression getCondImpl() { + List> list = Collections.emptyList(); - if ((ifStmt.getCondition() instanceof Expr)) { - list = Arrays.asList(CxxJoinpoints.create(ifStmt.getCondition(), getWeaverEngine(), AExpression.class)); + if ((this.getNodeImpl().getCondition() instanceof Expr)) { + list = Arrays.asList(CxxJoinpoints.create(this.getNodeImpl().getCondition(), getWeaverEngine(), AExpression.class)); } return SpecsCollections.orElseNull(list); } @Override - public AVardecl getCondDeclImpl() { - return SpecsCollections.orElseNull(SpecsCollections.toList(ifStmt.getDeclCondition() + public AVardecl getCondDeclImpl() { + return SpecsCollections.orElseNull(SpecsCollections.toList(this.getNodeImpl().getDeclCondition() .map(varDecl -> CxxJoinpoints.create(varDecl, getWeaverEngine(), AVardecl.class)))); } @Override - public AScope getThenImpl() { + public AScope getThenImpl() { return SpecsCollections.orElseNull( - ifStmt.getThen().map(then -> Arrays.asList(CxxJoinpoints.create(then, + this.getNodeImpl().getThen().map(then -> Arrays.asList(CxxJoinpoints.create(then, getWeaverEngine(), AScope.class))) .orElse(Collections.emptyList())); } @Override - public AScope getElseImpl() { - return SpecsCollections.orElseNull(SpecsCollections.toStream(ifStmt.getElse()) + public AScope getElseImpl() { + return SpecsCollections.orElseNull(SpecsCollections.toStream(this.getNodeImpl().getElse()) .map(stmt -> CxxJoinpoints.create(stmt, getWeaverEngine(), AScope.class)) .collect(Collectors.toList())); } @Override - public void setCondImpl(AExpression cond) { - ifStmt.setCondition((Expr) cond.getNode()); + public void setCondImpl(AExpression cond) { + this.getNodeImpl().setCondition((Expr) cond.getNodeImpl()); } @Override - public void setThenImpl(AStatement then) { - ifStmt.setThen((Stmt) then.getNode()); + public void setThenImpl(AStatement then) { + this.getNodeImpl().setThen((Stmt) then.getNodeImpl()); } @Override - public void setElseImpl(AStatement _else) { - ifStmt.setElse((Stmt) _else.getNode()); + public void setElseImpl(AStatement _else) { + this.getNodeImpl().setElse((Stmt) _else.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxImplicitValue.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxImplicitValue.java index 8942625528..e438428aa7 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxImplicitValue.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxImplicitValue.java @@ -13,22 +13,18 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.ImplicitValueInitExpr; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AImplicitValue; -public class CxxImplicitValue extends AImplicitValue { - - private final ImplicitValueInitExpr implicitValue; +public class CxxImplicitValue> extends AImplicitValue { public CxxImplicitValue(ImplicitValueInitExpr implicitValue, CxxWeaver weaver) { - super(new CxxExpression(implicitValue, weaver), weaver); - this.implicitValue = implicitValue; + super(implicitValue, weaver); } @Override - public ClavaNode getNode() { - return implicitValue; + public ImplicitValueInitExpr getNodeImpl() { + return (ImplicitValueInitExpr) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInclude.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInclude.java index b150bb4621..e5982aaf2a 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInclude.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInclude.java @@ -13,43 +13,39 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.IncludeDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AInclude; -public class CxxInclude extends AInclude { - - private final IncludeDecl include; +public class CxxInclude> extends AInclude { public CxxInclude(IncludeDecl include, CxxWeaver weaver) { - super(new CxxDecl(include, weaver), weaver); - this.include = include; + super(include, weaver); } @Override - public ClavaNode getNode() { - return include; + public IncludeDecl getNodeImpl() { + return (IncludeDecl) super.getNodeImpl(); } @Override public String getNameImpl() { - return include.getInclude().getInclude(); + return this.getNodeImpl().getInclude().getInclude(); } @Override - public Boolean getIsAngledImpl() { - return include.getInclude().isAngled(); + public boolean getIsAngledImpl() { + return this.getNodeImpl().getInclude().isAngled(); } @Override public String getFilepathImpl() { - return include.getInclude().getSourceFile().getAbsolutePath(); + return this.getNodeImpl().getInclude().getSourceFile().getAbsolutePath(); } @Override public String getRelativeFolderpathImpl() { - return include.getInclude().getRelativeFolder().getAbsolutePath(); + return this.getNodeImpl().getInclude().getRelativeFolder().getAbsolutePath(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInitList.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInitList.java index aa82d92145..51207f553e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInitList.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxInitList.java @@ -13,31 +13,26 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.InitListExpr; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AInitList; -public class CxxInitList extends AInitList { - - private final InitListExpr initList; +public class CxxInitList> extends AInitList { public CxxInitList(InitListExpr initList, CxxWeaver weaver) { - super(new CxxExpression(initList, weaver), weaver); - - this.initList = initList; + super(initList, weaver); } @Override - public ClavaNode getNode() { - return initList; + public InitListExpr getNodeImpl() { + return (InitListExpr) super.getNodeImpl(); } @Override - public AExpression getArrayFillerImpl() { - return initList.get(InitListExpr.ARRAY_FILLER) + public AExpression getArrayFillerImpl() { + return this.getNodeImpl().get(InitListExpr.ARRAY_FILLER) .map(n -> CxxJoinpoints.create(n, getWeaverEngine(), AExpression.class)) .orElse(null); diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIntLiteral.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIntLiteral.java index 6d9d6bc256..cb28d3d3c7 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIntLiteral.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxIntLiteral.java @@ -13,30 +13,23 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.IntegerLiteral; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AIntLiteral; -public class CxxIntLiteral extends AIntLiteral { - - private final IntegerLiteral literal; +public class CxxIntLiteral> extends AIntLiteral { public CxxIntLiteral(IntegerLiteral literal, CxxWeaver weaver) { - super(new CxxLiteral(literal, weaver), weaver); - - this.literal = literal; + super(literal, weaver); } @Override - public ClavaNode getNode() { - return literal; + public IntegerLiteral getNodeImpl() { + return (IntegerLiteral) super.getNodeImpl(); } @Override - public Long getValueImpl() { - return literal.get(IntegerLiteral.VALUE).longValue(); + public long getValueImpl() { + return this.getNodeImpl().get(IntegerLiteral.VALUE).longValue(); } - - } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/ACxxWeaverJoinPoint.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxJoinpoint.java similarity index 53% rename from ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/ACxxWeaverJoinPoint.java rename to ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxJoinpoint.java index 7e18d27c83..7d24619fb4 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/abstracts/ACxxWeaverJoinPoint.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxJoinpoint.java @@ -1,9 +1,25 @@ -package pt.up.fe.specs.clava.weaver.abstracts; +package pt.up.fe.specs.clava.weaver.joinpoints; -import com.google.common.base.Preconditions; -import org.lara.interpreter.weaver.interf.JoinPoint; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.lara.interpreter.weaver.interf.enums.InsertPosition; import org.suikasoft.jOptions.Datakey.DataKey; import org.suikasoft.jOptions.storedefinition.StoreDefinition; + +import com.google.common.base.Preconditions; + import pt.up.fe.specs.clava.ClavaLog; import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaNodes; @@ -20,8 +36,18 @@ import pt.up.fe.specs.clava.utils.NodeWithScope; import pt.up.fe.specs.clava.utils.NullNode; import pt.up.fe.specs.clava.utils.Typable; -import pt.up.fe.specs.clava.weaver.*; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.*; +import pt.up.fe.specs.clava.weaver.CxxActions; +import pt.up.fe.specs.clava.weaver.CxxAttributes; +import pt.up.fe.specs.clava.weaver.CxxJoinpoints; +import pt.up.fe.specs.clava.weaver.CxxSelects; +import pt.up.fe.specs.clava.weaver.CxxWeaver; +import pt.up.fe.specs.clava.weaver.Insert; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AComment; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.APragma; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AProgram; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; import pt.up.fe.specs.clava.weaver.importable.AstFactory; import pt.up.fe.specs.clava.weaver.importable.LowLevelApi; import pt.up.fe.specs.util.SpecsLogs; @@ -30,21 +56,14 @@ import pt.up.fe.specs.util.stringsplitter.StringSplitter; import pt.up.fe.specs.util.stringsplitter.StringSplitterRules; -import java.io.File; -import java.util.*; -import java.util.Map.Entry; -import java.util.stream.Collectors; -import java.util.stream.Stream; - /** - * Abstract class which can be edited by the developer. This class will not be overwritten. - * - * @author Lara Weaver Generator + * Abstract class which can be edited by the developer. + * This class will NOT be overwritten by the generator. */ -public abstract class ACxxWeaverJoinPoint extends AJoinPoint { +public class CxxJoinpoint> extends AJoinpoint { - public ACxxWeaverJoinPoint(CxxWeaver weaver) { - super(weaver); + public CxxJoinpoint(ClavaNode node, CxxWeaver weaver) { + super(node, weaver); } @Override @@ -52,11 +71,10 @@ public CxxWeaver getWeaverEngine() { return (CxxWeaver) super.getWeaverEngine(); } - // private static final String BASE_CLAVA_AST_PACKAGE = "pt.up.fe.specs.clava.ast"; - // - // protected static String getBaseClavaAstPackage() { - // return BASE_CLAVA_AST_PACKAGE; - // } + @Override + public boolean getSameImpl(AJoinpoint other) { + return this.get_class().equals(other.get_class()) && this.getNodeImpl().equals(other.getNodeImpl()); + } private static final Set> IGNORE_NODES; @@ -70,21 +88,6 @@ public ClavaFactory getFactory() { return getWeaverEngine().getFactory(); } - /** - * Implementation of GET_NAME. Returns null if no mapping is found. - */ - /* - private static final String GET_NAME_DEFAULT = "!NO_NAME!"; - private static final FunctionClassMap GET_NAME; - static { - GET_NAME = new FunctionClassMap<>(GET_NAME_DEFAULT); - GET_NAME.put(NamedDecl.class, namedDecl -> namedDecl.hasDeclName() ? namedDecl.getDeclName() : null); - GET_NAME.put(TagType.class, tagType -> tagType.getDeclInfo().getDeclName()); - GET_NAME.put(DeclRefExpr.class, declRef -> declRef.getRefName()); - GET_NAME.put(Stmt.class, stmt -> stmt.getClass().getSimpleName()); - } - */ - /** * Compares the two join points based on their node reference of the used compiler/parsing tool.
    * This is the default implementation for comparing two join points.
    @@ -92,108 +95,91 @@ public ClavaFactory getFactory() { * changes are made for all join points, or override this method in specific join points. */ @Override - public boolean compareNodes(AJoinPoint aJoinPoint) { - return getNode().equals(aJoinPoint.getNode()); + public boolean getCompareNodesImpl(AJoinpoint aJoinPoint) { + return this.getNodeImpl().equals(aJoinPoint.getNodeImpl()); } @Override - public AProgram getRootImpl() { + public AProgram getRootImpl() { return getWeaverEngine().getAppJp(); - /* - ACxxWeaverJoinPoint current = this; - while (current.getHasParentImpl()) { - current = current.getParentImpl(); - } - - - return (current instanceof CxxProgram) ? (CxxProgram) current : null; - */ - // Preconditions.checkArgument(current instanceof CxxProgram, - // "Expected root joinpoint to be a CxxProgram, it is a '" + current.getClass().getSimpleName() + "'"); - // - // return (CxxProgram) current; } /** * @return the parent joinpoint */ @Override - public AJoinPoint getParentImpl() { - ClavaNode node = getNode(); + public AJoinpoint getParentImpl() { + ClavaNode node = getNodeImpl(); if (!node.hasParent()) { return null; } ClavaNode currentParent = node.getParent(); - // if (currentParent instanceof WrapperStmt) { - // currentParent = currentParent.getParent(); - // } return CxxJoinpoints.create(currentParent, getWeaverEngine()); } @Override - public JoinPoint getJpParent() { + public AJoinpoint getJpParent() { return getParentImpl(); } @Override - public AJoinPoint getAncestorImpl(String type) { + public AJoinpoint getGetAncestorImpl(String type) { Objects.requireNonNull(type, () -> "Missing type of ancestor in attribute 'ancestor'"); if (type.equals("program")) { ClavaLog.warning("Consider using attribute .root, instead of .ancestor('program')"); } - ClavaNode currentNode = getNode(); + ClavaNode currentNode = getNodeImpl(); while (currentNode.hasParent()) { // Create join point for testing type - ACxxWeaverJoinPoint parentJp = CxxJoinpoints.create(currentNode.getParent(), getWeaverEngine()); + AJoinpoint parentJp = CxxJoinpoints.create(currentNode.getParent(), getWeaverEngine()); - if (parentJp.instanceOf(type)) { + if (parentJp.getInstanceOfImpl(type)) { return parentJp; } - currentNode = parentJp.getNode(); + currentNode = parentJp.getNodeImpl(); } return null; } @Override - public AJoinPoint[] getDescendantsArrayImpl(String type) { + public AJoinpoint[] getGetDescendantsImpl(String type) { Objects.requireNonNull(type, () -> "Missing type of descendants in attribute 'descendants'"); - return CxxSelects.selectedNodesToJps(getNode().getDescendantsStream(), jp -> jp.instanceOf(type), + return CxxSelects.selectedNodesToJps(getNodeImpl().getDescendantsStream(), jp -> jp.getInstanceOfImpl(type), getWeaverEngine()); } @Override - public AJoinPoint[] getDescendantsArrayImpl() { - return CxxSelects.selectedNodesToJps(getNode().getDescendantsStream(), getWeaverEngine()); + public AJoinpoint[] getDescendantsImpl() { + return CxxSelects.selectedNodesToJps(getNodeImpl().getDescendantsStream(), getWeaverEngine()); } @Override - public AJoinPoint[] getDescendantsAndSelfArrayImpl(String type) { + public AJoinpoint[] getGetDescendantsAndSelfImpl(String type) { Objects.requireNonNull(type, () -> "Missing type of descendants in attribute 'descendants'"); - return CxxSelects.selectedNodesToJps(getNode().getDescendantsAndSelfStream(), jp -> jp.instanceOf(type), + return CxxSelects.selectedNodesToJps(getNodeImpl().getDescendantsAndSelfStream(), jp -> jp.getInstanceOfImpl(type), getWeaverEngine()); } @Override - public AJoinPoint getChainAncestorImpl(String type) { + public AJoinpoint getGetChainAncestorImpl(String type) { Objects.requireNonNull(type, () -> "Missing type of ancestor in attribute 'chainAncestor'"); if (type.equals("program")) { ClavaLog.warning("Consider using attribute .root, instead of .chainAncestor('program')"); } - AJoinPoint currentJp = this; + AJoinpoint currentJp = this; while (currentJp.getHasParentImpl()) { var parentJp = currentJp.getParentImpl(); - // if (parentJp.getJoinpointType().equals(type)) { - if (parentJp.instanceOf(type)) { + if (parentJp.getInstanceOfImpl(type)) { return parentJp; } @@ -204,13 +190,13 @@ public AJoinPoint getChainAncestorImpl(String type) { } @Override - public AJoinPoint getAstAncestorImpl(String type) { + public AJoinpoint getGetAstAncestorImpl(String type) { Objects.requireNonNull(type, () -> "Missing type of ancestor in attribute 'astAncestor'"); // Obtain ClavaNode class from type Class nodeClass = ClassesService.getClavaClass(type); - ClavaNode currentNode = getNode(); + ClavaNode currentNode = getNodeImpl(); while (currentNode.hasParent()) { ClavaNode parentNode = currentNode.getParent(); @@ -225,101 +211,96 @@ public AJoinPoint getAstAncestorImpl(String type) { } @Override - public Boolean getHasParentImpl() { - return getNode().hasParent(); - // return getParentImpl() != null; + public boolean getHasParentImpl() { + return getNodeImpl().hasParent(); } @Override public String getAstImpl() { - return getNode().toTree(); + return getNodeImpl().toTree(); } @Override public String getCodeImpl() { - return getNode().getCode(); + return getNodeImpl().getCode(); } @Override public Integer getLineImpl() { - // ClavaNode node = getNode(); - // Objects.requireNonNull(node); - // int line = getNode().getLocation().getStartLine(); - // return line != SourceLocation.getInvalidLoc() ? line : null; - SourceRange location = getNode().getLocation(); + SourceRange location = getNodeImpl().getLocation(); return location.isValid() ? location.getStartLine() : null; - } @Override public Integer getColumnImpl() { - SourceRange location = getNode().getLocation(); + SourceRange location = getNodeImpl().getLocation(); return location.isValid() ? location.getStartCol() : null; } @Override public Integer getEndLineImpl() { - SourceRange location = getNode().getLocation(); + SourceRange location = getNodeImpl().getLocation(); return location.isValid() ? location.getEndLine() : null; } @Override public Integer getEndColumnImpl() { - SourceRange location = getNode().getLocation(); + SourceRange location = getNodeImpl().getLocation(); return location.isValid() ? location.getEndCol() : null; } @Override public String getFilenameImpl() { - SourceRange location = getNode().getLocation(); + SourceRange location = getNodeImpl().getLocation(); return location.isValid() ? location.getFilename() : null; } @Override public String getFilepathImpl() { - SourceRange location = getNode().getLocation(); + SourceRange location = getNodeImpl().getLocation(); return location.isValid() ? location.getFilepath() : null; } @Override - public AJoinPoint[] insertImpl(String position, String code) { - - Insert insert = Insert.getHelper().fromValue(position); - // CxxActions.in - - return new AJoinPoint[]{CxxActions.insertAsStmt(getNode(), code, insert, getWeaverEngine())}; - // - // if (insert == Insert.AFTER || insert == Insert.BEFORE) { - // Stmt literalStmt = ClavaNodeFactory.literalStmt(code); - // CxxActions.insertStmtAndBelow(getNode(), literalStmt, insert); - // return; - // } - + public AJoinpoint[] insertImpl(InsertPosition position, String code) { + Insert insert = Insert.getHelper().fromValue(position.getDisplay()); + return new AJoinpoint[]{CxxActions.insertAsStmt(getNodeImpl(), code, insert, getWeaverEngine())}; } @Override - public AJoinPoint[] insertImpl(String position, JoinPoint JoinPoint) { - throw new NotImplementedException(this); + public AJoinpoint[] insertImpl(InsertPosition position, AJoinpoint node) { + Insert insert = Insert.getHelper().fromValue(position.getDisplay()); + switch (insert) { + case AFTER: + return new AJoinpoint[]{insertAfterImpl(node)}; + case BEFORE: + return new AJoinpoint[]{insertBeforeImpl(node)}; + case REPLACE: + return new AJoinpoint[]{replaceWithImpl(node)}; + case AROUND: + default: + throw new NotImplementedException(insert); + } } @Override - public void setTypeImpl(AType type) { + public void setTypeImpl(AType type) { // Check if node has a type - ClavaNode node = getNode(); + ClavaNode node = getNodeImpl(); if (!(node instanceof Typable)) { - SpecsLogs.msgLib("[Ignore] Setting type ('" + type.getNode().getNodeName() + SpecsLogs.msgLib("[Ignore] Setting type ('" + type.getNodeImpl().getNodeName() + "') of a node that has no type ('" + node.getNodeName() + "')"); return; } - ((Typable) node).setType((Type) type.getNode()); + ((Typable) node).setType((Type) type.getNodeImpl()); } @Override - public AJoinPoint insertBeforeImpl(AJoinPoint node) { + public AJoinpoint insertBeforeImpl(AJoinpoint node) { // Check if type - if (node.getNode() instanceof Type) { + if (node.getNodeImpl() instanceof Type) { ClavaLog.info("Action 'insertBefore' not available for 'type' join points"); return null; } @@ -328,17 +309,15 @@ public AJoinPoint insertBeforeImpl(AJoinPoint node) { } @Override - public AJoinPoint insertBeforeImpl(String code) { - // return insertBeforeImpl(CxxJoinpoints.create(ClavaNodeFactory.literalStmt(code), this)); - // return insertBeforeImpl(CxxJoinpoints.create(CxxWeaver.getSnippetParser().parseStmt(code))); + public AJoinpoint insertBeforeImpl(String code) { return insertBeforeImpl(toJpToBeInserted(code)); } @Override - public AJoinPoint insertAfterImpl(AJoinPoint node) { + public AJoinpoint insertAfterImpl(AJoinpoint node) { // Check if type - if (node.getNode() instanceof Type) { + if (node.getNodeImpl() instanceof Type) { ClavaLog.info("Action 'insertAfter' not available for 'type' join points"); return null; } @@ -347,15 +326,15 @@ public AJoinPoint insertAfterImpl(AJoinPoint node) { } @Override - public AJoinPoint insertAfterImpl(String code) { + public AJoinpoint insertAfterImpl(String code) { return insertAfterImpl(toJpToBeInserted(code)); } - private AJoinPoint toJpToBeInserted(String code) { + private AJoinpoint toJpToBeInserted(String code) { // Special case: if this node is a statement in a loop header, insert as an expression if (this instanceof AStatement && getIsInsideLoopHeaderImpl()) { - if (getNode() instanceof DeclStmt) { + if (getNodeImpl() instanceof DeclStmt) { System.out.println("Code: " + code); // Convert to VarDecl var equalIndex = code.indexOf('='); @@ -389,13 +368,13 @@ private AJoinPoint toJpToBeInserted(String code) { return AstFactory.varDecl(getWeaverEngine(), declName, init); } - if (getNode() instanceof ExprStmt) { + if (getNodeImpl() instanceof ExprStmt) { return AstFactory.exprLiteral(getWeaverEngine(), code); } throw new RuntimeException( "Inserting before/after a loop header statement only support for 'declStmt' and 'exprStmt', this is a " - + getJoinPointType()); + + getJoinPointTypeImpl()); } @@ -403,62 +382,58 @@ private AJoinPoint toJpToBeInserted(String code) { } @Override - public AJoinPoint replaceWithImpl(AJoinPoint node) { - return CxxJoinpoints.create(CxxActions.replace(getNode(), node.getNode(), getWeaverEngine()), getWeaverEngine()); - - // Return input joinpoint - // return node; - + public AJoinpoint replaceWithImpl(AJoinpoint node) { + return CxxJoinpoints.create(CxxActions.replace(getNodeImpl(), node.getNodeImpl(), getWeaverEngine()), getWeaverEngine()); } @Override - public AJoinPoint replaceWithImpl(String node) { - return CxxActions.insertAsStmt(getNode(), node, Insert.REPLACE, getWeaverEngine()); + public AJoinpoint replaceWithImpl(String node) { + return CxxActions.insertAsStmt(getNodeImpl(), node, Insert.REPLACE, getWeaverEngine()); } @Override - public AJoinPoint replaceWithImpl(AJoinPoint[] node) { + public AJoinpoint replaceWithImpl(AJoinpoint[] node) { // Insert nodes after in reverse order, to preserve order of comments and pragmas var reverseNodes = Arrays.asList(node); Collections.reverse(reverseNodes); - AJoinPoint topInserted = null; + AJoinpoint topInserted = null; for (var nodeToInsert : reverseNodes) { topInserted = insertAfterImpl(nodeToInsert); } // Remove current node from the tree - detach(); + detachImpl(); // Return the first inserted element return topInserted; } @Override - public AJoinPoint replaceWithStringsImpl(String[] node) { + public AJoinpoint replaceWithStringsImpl(String[] node) { // Insert nodes after in reverse order, to preserve order of comments and pragmas var reverseNodes = Arrays.asList(node); Collections.reverse(reverseNodes); - AJoinPoint topInserted = null; + AJoinpoint topInserted = null; for (var nodeToInsert : reverseNodes) { topInserted = insertAfterImpl(nodeToInsert); } // Remove current node from the tree - detach(); + detachImpl(); // Return the first inserted element return topInserted; } @Override - public AJoinPoint detachImpl() { - ClavaNode node = getNode(); + public AJoinpoint detachImpl() { + ClavaNode node = getNodeImpl(); if (!node.hasParent()) { SpecsLogs.msgInfo( - "action detach: could not find a parent in joinpoint of type '" + getJoinPointType() + "'"); + "action detach: could not find a parent in joinpoint of type '" + getJoinPointTypeImpl() + "'"); return this; } @@ -473,11 +448,11 @@ public AJoinPoint detachImpl() { } @Override - public AType getTypeImpl() { - ClavaNode node = getNode(); + public AType getTypeImpl() { + ClavaNode node = getNodeImpl(); if (!(node instanceof Typable)) { - SpecsLogs.msgInfo("Joinpoint of type '" + getJoinPointType() + "' with node '" + node.getNodeName() + SpecsLogs.msgInfo("Joinpoint of type '" + getJoinPointTypeImpl() + "' with node '" + node.getNodeName() + "' does not have a type"); return null; } @@ -486,81 +461,30 @@ public AType getTypeImpl() { } @Override - public Boolean getHasTypeImpl() { - ClavaNode node = getNode(); + public boolean getHasTypeImpl() { + ClavaNode node = getNodeImpl(); return node instanceof Typable; } - // @Override - // public String toString() { - // return "Joinpoint '" + getJoinpointType() + "'"; - // } - /** * In case a joinpoint child needs to access the list of the parent joinpoint statements. * * @return */ - public List selectStatements() { + public List> selectStatements() { throw new RuntimeException("Not supported for joinpoint '" + getClass() + "'"); } - /* - @Override - public String getName() { - - String name = GET_NAME.apply(getNodeNormalized()); - - if (name != null && name.equals(GET_NAME_DEFAULT)) { - CxxLog.warning("attribute 'name' not implemented for joinpoint '" + getClass().getSimpleName() + "'"); - return null; - } - - return name; - /* - // TODO: Add .getName() to ClavaNode, returning an Optional - - // ClavaNode node = getNode(); - ClavaNode node = getNodeNormalized(); - if (node instanceof NamedDecl) { - NamedDecl namedDecl = ((NamedDecl) node); - return namedDecl.hasDeclName() ? namedDecl.getDeclName() : null; - } - - // if (node instanceof Type) { - // return node.getNodeName(); - // } - - if (node instanceof TagType) { - return ((TagType) node).getDeclInfo().getDeclName(); - } - - if (node instanceof DeclRefExpr) { - return ((DeclRefExpr) node).getRefName(); - } - - if (node instanceof Stmt) { - return ((Stmt) node).getClass().getSimpleName(); - } - - CxxLog.warning("attribute 'name' not implemented for joinpoint '" + getClass().getSimpleName() + "'"); - return null; - // throw new RuntimeException( - // "attribute 'name' not implemented for joinpoint '" + getClass().getSimpleName() + "'"); - // return ""; - * - */ - // } @Override public String getLocationImpl() { - return getNode().getLocation().toString(); + return getNodeImpl().getLocation().toString(); } @Override - public Boolean containsImpl(AJoinPoint jp) { - ClavaNode clavaNode = jp.getNode(); + public boolean getContainsImpl(AJoinpoint jp) { + ClavaNode clavaNode = jp.getNodeImpl(); - return getNode().getDescendantsStream() + return getNodeImpl().getDescendantsStream() .filter(child -> child == clavaNode) .findFirst().isPresent(); } @@ -571,7 +495,7 @@ public Boolean containsImpl(AJoinPoint jp) { * @return */ public ClavaNode getNodeNormalized() { - ClavaNode currentNode = getNode(); + ClavaNode currentNode = getNodeImpl(); while (IGNORE_NODES.contains(currentNode.getClass())) { Preconditions.checkArgument(currentNode.getNumChildren() == 1, @@ -583,9 +507,9 @@ public ClavaNode getNodeNormalized() { } @Override - public Integer getAstNumChildrenImpl() { + public int getAstNumChildrenImpl() { // return getAstChildrenArrayImpl().length; - ClavaNode node = getNode(); + ClavaNode node = getNodeImpl(); if (node == null) { return -1; } @@ -594,18 +518,18 @@ public Integer getAstNumChildrenImpl() { } @Override - public AJoinPoint[] getAstChildrenArrayImpl() { - return getNode().getChildren().stream() + public AJoinpoint[] getAstChildrenImpl() { + return getNodeImpl().getChildren().stream() .map(node -> CxxJoinpoints.create(node, getWeaverEngine())) // .filter(jp -> jp != null) .collect(Collectors.toList()) - .toArray(new AJoinPoint[0]); + .toArray(new AJoinpoint[0]); } @Override - public AJoinPoint getAstChildImpl(int index) { - ClavaNode node = getNode(); + public AJoinpoint getGetAstChildImpl(int index) { + ClavaNode node = getNodeImpl(); if (node == null) { return null; } @@ -620,9 +544,8 @@ public AJoinPoint getAstChildImpl(int index) { } @Override - public Integer getNumChildrenImpl() { - return (int) getNode().getChildren().stream() - // return (int) getChildrenPrivate().stream() + public int getNumChildrenImpl() { + return (int) getNodeImpl().getChildren().stream() .filter(node -> !(node instanceof NullNode)) .count(); } @@ -634,11 +557,11 @@ public Integer getNumChildrenImpl() { * @return */ @Override - public AJoinPoint[] getScopeNodesArrayImpl() { - var node = getNode(); + public AJoinpoint[] getScopeNodesImpl() { + var node = getNodeImpl(); if (!(node instanceof NodeWithScope)) { - return new AJoinPoint[0]; + return new AJoinpoint[0]; } var stream = ((NodeWithScope) node).getNodeScope() @@ -649,69 +572,57 @@ public AJoinPoint[] getScopeNodesArrayImpl() { } @Override - public Stream getJpChildrenStream() { - return CxxSelects.selectedNodesToJpsStream(getNode().getChildren().stream(), getWeaverEngine()) - .map(JoinPoint.class::cast); + public Stream> getJpChildrenStream() { + return CxxSelects.selectedNodesToJpsStream(getNodeImpl().getChildren().stream(), getWeaverEngine()); } @Override - public AJoinPoint[] getChildrenArrayImpl() { - return CxxSelects.selectedNodesToJps(getNode().getChildren().stream(), getWeaverEngine()); + public AJoinpoint[] getChildrenImpl() { + return CxxSelects.selectedNodesToJps(getNodeImpl().getChildren().stream(), getWeaverEngine()); } @Override - public AJoinPoint[] getSiblingsRightArrayImpl() { - var siblingsRight = getNode().getSiblingsRight(); + public AJoinpoint[] getSiblingsRightImpl() { + var siblingsRight = getNodeImpl().getSiblingsRight(); return CxxSelects.selectedNodesToJps(siblingsRight.stream(), getWeaverEngine()); } @Override - public AJoinPoint[] getSiblingsLeftArrayImpl() { - var siblingsLeft = getNode().getSiblingsLeft(); + public AJoinpoint[] getSiblingsLeftImpl() { + var siblingsLeft = getNodeImpl().getSiblingsLeft(); return CxxSelects.selectedNodesToJps(siblingsLeft.stream(), getWeaverEngine()); } @Override - public AJoinPoint getLeftJpImpl() { - return getNode().getLeft().map(node -> CxxJoinpoints.create(node, getWeaverEngine())).orElse(null); + public AJoinpoint getLeftJpImpl() { + return getNodeImpl().getLeft().map(node -> CxxJoinpoints.create(node, getWeaverEngine())).orElse(null); } @Override - public AJoinPoint getRightJpImpl() { - return getNode().getRight().map(node -> CxxJoinpoints.create(node, getWeaverEngine())).orElse(null); + public AJoinpoint getRightJpImpl() { + return getNodeImpl().getRight().map(node -> CxxJoinpoints.create(node, getWeaverEngine())).orElse(null); } @Override - public AJoinPoint getChildImpl(int index) { - return getNode().getChildren().stream() - // return getChildrenPrivate().stream() + public AJoinpoint getGetChildImpl(int index) { + return getNodeImpl().getChildren().stream() .filter(node -> !(node instanceof NullNode)) .skip(index) .findFirst() .map(node -> CxxJoinpoints.create(node, getWeaverEngine())) .orElse(null); - - // AJoinPoint[] children = getChildrenArrayImpl(); - // - // if (index >= children.length) { - // ClavaLog.warning( - // "Index '" + index + "' is out of range, node only has " + children.length + " defined children"); - // return null; - // } - // - // return children.; } @Override - public String[] getChainArrayImpl() { + public String[] getChainImpl() { List chain = new ArrayList<>(); - AJoinPoint currentJoinpoint = this; + AJoinpoint currentJoinpoint = this; while (currentJoinpoint != null) { // Add joinpoint to chain - chain.add(currentJoinpoint.getJoinPointType()); + chain.add(currentJoinpoint.getJoinPointTypeImpl()); // Update current joinpoint if (currentJoinpoint.getHasParentImpl()) { @@ -739,33 +650,32 @@ public String getAstNameImpl() { } @Override - public String[] getJavaFieldsArrayImpl() { - return LowLevelApi.getFields(getNode()).toArray(new String[0]); + public String[] getJavaFieldsImpl() { + return LowLevelApi.getFields(getNodeImpl()).toArray(new String[0]); } @Override - public String getJavaFieldTypeImpl(String fieldName) { - return LowLevelApi.getFieldClass(getNode(), fieldName).getName(); + public String getGetJavaFieldTypeImpl(String fieldName) { + return LowLevelApi.getFieldClass(getNodeImpl(), fieldName).getName(); } @Override public String getAstIdImpl() { - // return getNode().getExtendedId().orElse(""); - return getNode().getExtendedId().orElseThrow(() -> new RuntimeException("No ID found in node " + getNode())); + return getNodeImpl().getExtendedId().orElseThrow(() -> new RuntimeException("No ID found in node " + getNodeImpl())); } @Override - public Boolean getIsInsideLoopHeaderImpl() { - return CxxAttributes.isInsideLoopHeader(getNode()); + public boolean getIsInsideLoopHeaderImpl() { + return CxxAttributes.isInsideLoopHeader(getNodeImpl()); } @Override - public Boolean getIsInsideHeaderImpl() { - return CxxAttributes.isInsideCHeader(getNode()); + public boolean getIsInsideHeaderImpl() { + return CxxAttributes.isInsideCHeader(getNodeImpl()); } @Override - public Object getUserFieldImpl(String fieldName) { + public Object getGetUserFieldImpl(String fieldName) { return getWeaverEngine().getUserField(getNodeNormalized(), fieldName); } @@ -775,67 +685,30 @@ public Object setUserFieldImpl(String fieldName, Object value) { } @Override - public Object setUserFieldImpl(Map fieldNameAndValue) { + public Object setUserFieldImpl(Map fieldNameAndValue) { Object lastPrevious = null; - for (Entry entry : fieldNameAndValue.entrySet()) { - lastPrevious = setUserField(entry.getKey().toString(), entry.getValue()); + for (Entry entry : fieldNameAndValue.entrySet()) { + lastPrevious = setUserFieldImpl(entry.getKey(), entry.getValue()); } return lastPrevious; } - // @Override - // public Object setUserFieldImpl(Object fieldNameAndValue) { - // System.out.println("CLASS:" + fieldNameAndValue.getClass()); - // System.out.println("VALUE:" + fieldNameAndValue); - // return super.setUserFieldImpl(fieldNameAndValue); - // } @Override - public AJoinPoint getParentRegionImpl() { - - return CxxAttributes.getParentRegion(getNode()) + public AJoinpoint getParentRegionImpl() { + return CxxAttributes.getParentRegion(getNodeImpl()) .map(node -> CxxJoinpoints.create(node, getWeaverEngine())) .orElse(null); - /* - Optional parentRegionTry = CxxAttributes.getParentRegion(getNode()); - - if (!parentRegionTry.isPresent()) { - ClavaLog.info("Join point '" + getJoinPointType() + "' does not support parentRegion"); - return null; - } - - return CxxJoinpoints.create(parentRegionTry.get(), this); - */ - /* - // Get current region - ClavaNode currentRegion = getCurrentRegion(getNode()); - if (currentRegion == null) { - ClavaLog.info("Join point '" + getJoinPointType() + "' does not support parentRegion"); - return null; - } - - // If already at top region, return that node - if (currentRegion instanceof TranslationUnit) { - return CxxJoinpoints.create(currentRegion, this); - } - System.out.println("CURRENT REGION:" + currentRegion.getNodeName() + ", " + currentRegion.getLocation()); - System.out.println( - "PARENT:" + currentRegion.getParent().getNodeName() + ", " + currentRegion.getParent().getLocation()); - System.out.println("PARENT REGION" + getCurrentRegion(currentRegion.getParent()).getNodeName() + ", " - + getCurrentRegion(currentRegion.getParent()).getLocation()); - // Go up one node, and return the current region - return CxxJoinpoints.create(getCurrentRegion(currentRegion.getParent()), this); - */ } @Override - public AJoinPoint getCurrentRegionImpl() { - Optional currentRegionTry = CxxAttributes.getCurrentRegion(getNode()); + public AJoinpoint getCurrentRegionImpl() { + Optional currentRegionTry = CxxAttributes.getCurrentRegion(getNodeImpl()); if (!currentRegionTry.isPresent()) { ClavaLog.info( - "Join point '" + getJoinPointType() + "'@" + getLocationImpl() + " does not support currentRegion"); + "Join point '" + getJoinPointTypeImpl() + "'@" + getLocationImpl() + " does not support currentRegion"); return null; } @@ -843,39 +716,37 @@ public AJoinPoint getCurrentRegionImpl() { } @Override - public boolean equals(Object obj) { - if (!(obj instanceof AJoinPoint)) { + public boolean getEqualsImpl(Self jp) { + if (!(jp instanceof AJoinpoint)) { return false; } - // System.out.println("Equals? " + getNode().equals(((AJoinPoint) obj).getNode())); - // System.out.println("Node 1:" + getNode()); - // System.out.println("Node 2:" + ((AJoinPoint) obj).getNode()); - return getNode().equals(((AJoinPoint) obj).getNode()); + + return this.getSameImpl(jp); } @Override public int hashCode() { - return getNode().hashCode(); + return getNodeImpl().hashCode(); } @Override - public AJoinPoint copyImpl() { - return CxxJoinpoints.create(getNode().copy(), getWeaverEngine()); + public AJoinpoint copyImpl() { + return CxxJoinpoints.create(getNodeImpl().copy(), getWeaverEngine()); } @Override - public AJoinPoint deepCopyImpl() { - return CxxJoinpoints.create(getNode().deepCopy(), getWeaverEngine()); + public AJoinpoint deepCopyImpl() { + return CxxJoinpoints.create(getNodeImpl().deepCopy(), getWeaverEngine()); } @Override - public Boolean hasNodeImpl(Object nodeOrJp) { - if (nodeOrJp instanceof AJoinPoint) { - return hasNodeImpl(((AJoinPoint) nodeOrJp).getNode()); + public boolean getHasNodeImpl(Object nodeOrJp) { + if (nodeOrJp instanceof AJoinpoint) { + return getHasNodeImpl(((AJoinpoint) nodeOrJp).getNodeImpl()); } if (nodeOrJp instanceof ClavaNode) { - return getNode() == nodeOrJp; + return getNodeImpl() == nodeOrJp; } ClavaLog.warning("joinpoint attribute 'hasNode': input type '" + nodeOrJp.getClass() @@ -887,18 +758,11 @@ public Boolean hasNodeImpl(Object nodeOrJp) { * @return the base ClavaAst class for this kind of nodes. */ private String getBaseClavaNodePackage() { - return getNode().getClass().getPackage().getName(); + return getNodeImpl().getClass().getPackage().getName(); } - // @Override - // public List selectDescendant() { - // return getNode().getDescendantsStream() - // .map(descendant -> CxxJoinpoints.create(descendant, this)) - // .collect(Collectors.toList()); - // } - @Override - public Boolean astIsInstanceImpl(String className) { + public boolean getAstIsInstanceImpl(String className) { // Assume nodes are in the same package String packageName = getBaseClavaNodePackage(); @@ -915,7 +779,7 @@ public Boolean astIsInstanceImpl(String className) { String fullClassName = packageName + "." + className; try { - return Class.forName(fullClassName).isInstance(getNode()); + return Class.forName(fullClassName).isInstance(getNodeImpl()); } catch (ClassNotFoundException e) { SpecsLogs.msgInfo("Could not find class '" + fullClassName + "' to compare against this node"); return false; @@ -923,10 +787,10 @@ public Boolean astIsInstanceImpl(String className) { } @Override - public APragma[] getPragmasArrayImpl() { - return ClavaNodes.getPragmas(getNode()).stream() + public APragma[] getPragmasImpl() { + return ClavaNodes.getPragmas(getNodeImpl()).stream() .map(pragma -> CxxJoinpoints.create(pragma, getWeaverEngine())) - .toArray(APragma[]::new); + .toArray(APragma[]::new); } static int jsNameCounter = 0; @@ -935,12 +799,12 @@ public APragma[] getPragmasArrayImpl() { public Object getDataImpl() { // Check if data object already exists - if (ClavaData.hasData(getNode())) { + if (ClavaData.hasData(getNodeImpl())) { // Return data object from managed cache - return ClavaData.getCacheData(getNode()); + return ClavaData.getCacheData(getNodeImpl()); } - var dataPragma = ClavaData.getClavaData(getNode()); + var dataPragma = ClavaData.getClavaData(getNodeImpl()); // TODO: Refactor, so that decoding of pragma is done separately // TODO: life-cycle management of data objects according to node id @@ -948,7 +812,7 @@ public Object getDataImpl() { // Pragma exists and data has not been created yet // if (!hasClavaData && dataPragma != null) { if (dataPragma != null) { - ClavaNode node = getNode(); + ClavaNode node = getNodeImpl(); TranslationUnit tu = node instanceof TranslationUnit ? (TranslationUnit) node : node.getAncestorTry(TranslationUnit.class).orElse(null); @@ -975,7 +839,7 @@ public Object getDataImpl() { } try { - ClavaData.setData(getNode(), sanitizedJsonString); + ClavaData.setData(getNodeImpl(), sanitizedJsonString); } catch (Exception e) { SpecsLogs.warn( @@ -988,31 +852,31 @@ public Object getDataImpl() { // Create cache object and repeat the process dataClearImpl(); - return ClavaData.getCacheData(getNode()); + return ClavaData.getCacheData(getNodeImpl()); } @Override public void setDataImpl(Object source) { - var dataPragma = ClavaData.getClavaData(getNode()); + var dataPragma = ClavaData.getClavaData(getNodeImpl()); if (dataPragma == null) { - ClavaData.buildClavaData(getNode()); + ClavaData.buildClavaData(getNodeImpl()); } String sanitizedJson = ClavaData.sanitizeJsonString(source.toString()); - ClavaData.setData(getNode(), sanitizedJson); + ClavaData.setData(getNodeImpl(), sanitizedJson); } @Override public void dataClearImpl() { // TODO: Remove pragma entirely - ClavaData.clearData(getNode()); + ClavaData.clearData(getNodeImpl()); } @Override - public String[] getKeysArrayImpl() { - List keys = new ArrayList<>(getNode().getStoreDefinition() + public String[] getKeysImpl() { + List keys = new ArrayList<>(getNodeImpl().getStoreDefinition() .getKeyMap() .keySet()); @@ -1023,34 +887,34 @@ public String[] getKeysArrayImpl() { } @Override - public Object getValueImpl(String key) { - var keys = getNode().getStoreDefinition(); + public Object getGetValueImpl(String key) { + var keys = getNodeImpl().getStoreDefinition(); if (!keys.hasKey(key)) { - ClavaLog.info("getValue(): key '" + key + "' not supported for join point '" + getJoinPointType() + "'"); + ClavaLog.info("getValue(): key '" + key + "' not supported for join point '" + getJoinPointTypeImpl() + "'"); return null; } // Get key DataKey datakey = keys.getKey(key); - var value = getNode().get(datakey); + var value = getNodeImpl().get(datakey); return CxxAttributes.toLara(value, getWeaverEngine()); } @Override - public AJoinPoint setValueImpl(String key, Object value) { + public AJoinpoint setValueImpl(String key, Object value) { // Get key - DataKey datakey = getNode().getStoreDefinition().getKeyRaw(key); + DataKey datakey = getNodeImpl().getStoreDefinition().getKeyRaw(key); // If string, use decoder - if (value instanceof String) { - value = datakey.decode((String) value); + if (value instanceof String str) { + value = datakey.decode(str); } // If join point, use underlying node - if (value instanceof AJoinPoint) { - value = ((AJoinPoint) value).getNode(); + if (value instanceof AJoinpoint jp) { + value = jp.getNodeImpl(); } // Adapt to optional, if needed @@ -1060,12 +924,12 @@ public AJoinPoint setValueImpl(String key, Object value) { } // Returns new join point of the node - return CxxJoinpoints.create(getNode().set(datakey, value), getWeaverEngine()); + return CxxJoinpoints.create(getNodeImpl().set(datakey, value), getWeaverEngine()); } @Override - public Object getKeyTypeImpl(String key) { - StoreDefinition def = getNode().getStoreDefinition(); + public Object getGetKeyTypeImpl(String key) { + StoreDefinition def = getNodeImpl().getStoreDefinition(); if (!def.hasKey(key)) { ClavaLog.info("$jp.keyType(): key '" + key + "' does not exist"); @@ -1076,31 +940,24 @@ public Object getKeyTypeImpl(String key) { } @Override - public AJoinPoint getFirstJpImpl(String type) { - AJoinPoint firstJp = getNode().getDescendantsStream() + public AJoinpoint getGetFirstJpImpl(String type) { + AJoinpoint firstJp = getNodeImpl().getDescendantsStream() .map(descendant -> CxxJoinpoints.create(descendant, getWeaverEngine())) - .filter(jp -> jp != null && jp.getJoinPointType().equals(type)) + .filter(jp -> jp != null && jp.getJoinPointTypeImpl().equals(type)) .findFirst() .orElse(null); if (firstJp == null) { ClavaLog.debug( - () -> "Could not find a join point '" + type + "' inside the node at " + getNode().getLocation()); + () -> "Could not find a join point '" + type + "' inside the node at " + getNodeImpl().getLocation()); } return firstJp; - // for (AJoinPoint descendant : getDescendantsArrayImpl()) { - // if (descendant.getJoinPointType().equals(type)) { - // return descendant; - // } - // } - // - // return null; } @Override - public Boolean getIsMacroImpl() { - return getNode().get(ClavaNode.IS_MACRO); + public boolean getIsMacroImpl() { + return getNodeImpl().get(ClavaNode.IS_MACRO); } @Override @@ -1108,36 +965,16 @@ public void messageToUserImpl(String message) { getWeaverEngine().addMessageToUser(message); } - /** - * Generic select function, used by the default select implementations. - * - * @param joinPointClass - * @param op - * @return - */ - // public List select(Class joinPointClass, SelectOp op) { - // // throw new RuntimeException( - // // "Generic select function not implemented yet. Implement it in order to use the default implementations of - // // select"); - // - // Predicate filter = node -> joinPointClass.isInstance(CxxJoinpoints.create(node, null)); - // - // return CxxSelects.select(joinPointClass, getNode().getChildren(), true, this, filter); - // } - - /** - * - */ @Override public void removeChildrenImpl() { - for (AJoinPoint child : getChildrenArrayImpl()) { + for (AJoinpoint child : getChildrenImpl()) { child.detachImpl(); } } @Override - public AJoinPoint getFirstChildImpl() { - ClavaNode node = getNode(); + public AJoinpoint getFirstChildImpl() { + ClavaNode node = getNodeImpl(); if (!node.hasChildren()) { return null; @@ -1147,24 +984,24 @@ public AJoinPoint getFirstChildImpl() { } @Override - public AJoinPoint setFirstChildImpl(AJoinPoint value) { + public AJoinpoint setFirstChildImpl(AJoinpoint value) { // If no children, just insert the node if (!getHasChildrenImpl()) { - getNode().addChild(value.getNode()); + getNodeImpl().addChild(value.getNodeImpl()); return null; } // Otherwise, replace node var firstChild = getFirstChildImpl(); - firstChild.replaceWith(value); + firstChild.replaceWithImpl(value); return firstChild; } @Override - public AJoinPoint getLastChildImpl() { + public AJoinpoint getLastChildImpl() { // Get last child from jp children, so that null nodes are ignored - var children = getChildrenArrayImpl(); + var children = getChildrenImpl(); if (children.length == 0) { return null; @@ -1174,41 +1011,41 @@ public AJoinPoint getLastChildImpl() { } @Override - public AJoinPoint setLastChildImpl(AJoinPoint value) { + public AJoinpoint setLastChildImpl(AJoinpoint value) { // If no children, just insert the node if (!getHasChildrenImpl()) { - getNode().addChild(value.getNode()); + getNodeImpl().addChild(value.getNodeImpl()); return null; } // Otherwise, replace node var lastChild = getLastChildImpl(); - lastChild.replaceWith(value); + lastChild.replaceWithImpl(value); return lastChild; } @Override - public Boolean getHasChildrenImpl() { - return getNode().hasChildren(); + public boolean getHasChildrenImpl() { + return getNodeImpl().hasChildren(); } @Override - public Boolean getIsCilkImpl() { - return getNode() instanceof CilkNode; + public boolean getIsCilkImpl() { + return getNodeImpl() instanceof CilkNode; } @Override - public Integer getDepthImpl() { - return getNode().getDepth(); + public int getDepthImpl() { + return getNodeImpl().getDepth(); } @Override public String getJpIdImpl() { - return getNode().getStableId(); + return getNodeImpl().getStableId(); } @Override - public AJoinPoint toCommentImpl(String prefix, String suffix) { + public AJoinpoint toCommentImpl(String prefix, String suffix) { var prefixClean = prefix == null ? "" : prefix; var suffixClean = suffix == null ? "" : suffix; @@ -1216,56 +1053,35 @@ public AJoinPoint toCommentImpl(String prefix, String suffix) { } @Override - public AStatement getStmtImpl() { - return ClavaNodes.toStmtTry(getNode()) + public AStatement getStmtImpl() { + return ClavaNodes.toStmtTry(getNodeImpl()) .map(stmt -> CxxJoinpoints.create(stmt, getWeaverEngine(), AStatement.class)) .orElse(null); } @Override public Integer getBitWidthImpl() { - AType type = getTypeImpl(); + AType type = getTypeImpl(); if (type == null) { return null; } - Type typeNode = (Type) type.getNode(); + Type typeNode = (Type) type.getNodeImpl(); - Integer bitwidth = typeNode.getBitwidth(this.getNode()); + Integer bitwidth = typeNode.getBitwidth(this.getNodeImpl()); return bitwidth != -1 ? bitwidth : null; } @Override - public AComment[] getInlineCommentsArrayImpl() { - return CxxJoinpoints.create(getNode().get(ClavaNode.INLINE_COMMENTS), getWeaverEngine(), AComment.class); + public AComment[] getInlineCommentsImpl() { + return CxxJoinpoints.create(getNodeImpl().get(ClavaNode.INLINE_COMMENTS), getWeaverEngine(), AComment.class); } - // @Override - // public void setInlineCommentsImpl(AComment[] comments) { - // defInlineCommentsImpl(comments); - // } - - // @Override - // public void defInlineCommentsImpl(AComment[] value) { - // if (value == null || value.length == 0) { - // getNode().removeInlineComments(); - // return; - // } - // - // // sArrays.stream(value).map(comment -> (Com)) - // - // var comments = Arrays.stream(value) - // .map(jp -> (Comment) jp.getNode()) - // .collect(Collectors.toList()); - // - // getNode().set(ClavaNode.INLINE_COMMENTS, comments); - // } - @Override public void setInlineCommentsImpl(String[] comments) { if (comments == null || comments.length == 0) { - getNode().removeInlineComments(); + getNodeImpl().removeInlineComments(); return; } @@ -1274,7 +1090,7 @@ public void setInlineCommentsImpl(String[] comments) { .map(comment -> getFactory().inlineComment(comment, false)) .collect(Collectors.toList()); - getNode().set(ClavaNode.INLINE_COMMENTS, newComments); + getNodeImpl().set(ClavaNode.INLINE_COMMENTS, newComments); } @Override public void setInlineCommentsImpl(String comment) { @@ -1287,21 +1103,21 @@ public void setInlineCommentsImpl(String comment) { } @Override - public Boolean getIsInSystemHeaderImpl() { - return getNode().get(ClavaNode.IS_IN_SYSTEM_HEADER); + public boolean getIsInSystemHeaderImpl() { + return getNodeImpl().get(ClavaNode.IS_IN_SYSTEM_HEADER); } @Override - public AJoinPoint getOriginNodeImpl() { - return CxxJoinpoints.create(getNode().getOrigin(), getWeaverEngine()); + public AJoinpoint getOriginNodeImpl() { + return CxxJoinpoints.create(getNodeImpl().getOrigin(), getWeaverEngine()); } @Override - public AJoinPoint[] jpFieldsArrayImpl(Boolean recursive) { + public AJoinpoint[] getJpFieldsImpl(boolean recursive) { if (recursive) { - return CxxJoinpoints.create(getNode().getNodeFieldsRecursive(), getWeaverEngine(), AJoinPoint.class); + return CxxJoinpoints.create(getNodeImpl().getNodeFieldsRecursive(), getWeaverEngine(), AJoinpoint.class); } - return CxxJoinpoints.create(getNode().getNodeFields(), getWeaverEngine(), AJoinPoint.class); + return CxxJoinpoints.create(getNodeImpl().getNodeFields(), getWeaverEngine(), AJoinpoint.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelDecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelDecl.java index 001b8ad71f..6963a3459e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelDecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelDecl.java @@ -13,30 +13,26 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.LabelDecl; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ALabelDecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ALabelStmt; -public class CxxLabelDecl extends ALabelDecl { - - private final LabelDecl labelDecl; +public class CxxLabelDecl> extends ALabelDecl { public CxxLabelDecl(LabelDecl labelDecl, CxxWeaver weaver) { - super(new CxxNamedDecl(labelDecl, weaver), weaver); - this.labelDecl = labelDecl; + super(labelDecl, weaver); } @Override - public ClavaNode getNode() { - return labelDecl; + public LabelDecl getNodeImpl() { + return (LabelDecl) super.getNodeImpl(); } @Override - public ALabelStmt getLabelStmtImpl() { - return labelDecl.get(LabelDecl.LABEL_STMT) + public ALabelStmt getLabelStmtImpl() { + return this.getNodeImpl().get(LabelDecl.LABEL_STMT) .map(labelStmt -> CxxJoinpoints.create(labelStmt, getWeaverEngine(), ALabelStmt.class)) .orElse(null); diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelStmt.java index a69b2c5c3d..72f6f5a95e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLabelStmt.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.LabelDecl; import pt.up.fe.specs.clava.ast.stmt.LabelStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,28 +20,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ALabelDecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ALabelStmt; -public class CxxLabelStmt extends ALabelStmt { - - private final LabelStmt labelStmt; +public class CxxLabelStmt> extends ALabelStmt { public CxxLabelStmt(LabelStmt labelStmt, CxxWeaver weaver) { - super(new CxxStatement(labelStmt, weaver), weaver); - this.labelStmt = labelStmt; + super(labelStmt, weaver); } @Override - public ALabelDecl getDeclImpl() { - return CxxJoinpoints.create(labelStmt.getLabelDecl(), getWeaverEngine(), ALabelDecl.class); + public LabelStmt getNodeImpl() { + return (LabelStmt) super.getNodeImpl(); } @Override - public void setDeclImpl(ALabelDecl label) { - labelStmt.setLabelDecl((LabelDecl) label.getNode()); + public ALabelDecl getDeclImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getLabelDecl(), getWeaverEngine(), ALabelDecl.class); } @Override - public ClavaNode getNode() { - return labelStmt; + public void setDeclImpl(ALabelDecl label) { + this.getNodeImpl().setLabelDecl((LabelDecl) label.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLiteral.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLiteral.java index cfdfaaba67..4d4d1170c6 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLiteral.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLiteral.java @@ -13,24 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.Literal; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ALiteral; -public class CxxLiteral extends ALiteral { - - private final Literal literal; +public class CxxLiteral> extends ALiteral { public CxxLiteral(Literal literal, CxxWeaver weaver) { - super(new CxxExpression(literal, weaver), weaver); - - this.literal = literal; + super(literal, weaver); } @Override - public ClavaNode getNode() { - return literal; + public Literal getNodeImpl() { + return (Literal) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLoop.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLoop.java index ec5356f716..42881c9c9e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLoop.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxLoop.java @@ -13,12 +13,28 @@ package pt.up.fe.specs.clava.weaver.joinpoints; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + import pt.up.fe.specs.clava.ClavaLog; import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaNodes; import pt.up.fe.specs.clava.ast.expr.BinaryOperator; import pt.up.fe.specs.clava.ast.expr.enums.BinaryOperatorKind; -import pt.up.fe.specs.clava.ast.stmt.*; +import pt.up.fe.specs.clava.ast.stmt.CXXForRangeStmt; +import pt.up.fe.specs.clava.ast.stmt.CompoundStmt; +import pt.up.fe.specs.clava.ast.stmt.DoStmt; +import pt.up.fe.specs.clava.ast.stmt.ForStmt; +import pt.up.fe.specs.clava.ast.stmt.LiteralStmt; +import pt.up.fe.specs.clava.ast.stmt.LoopStmt; +import pt.up.fe.specs.clava.ast.stmt.Stmt; +import pt.up.fe.specs.clava.ast.stmt.WhileStmt; import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.ast.type.enums.BuiltinKind; import pt.up.fe.specs.clava.transform.loop.LoopAnalysisUtils; @@ -26,27 +42,28 @@ import pt.up.fe.specs.clava.transform.loop.LoopTiling; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.*; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.enums.ALoopKindEnum; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ALoop; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AScope; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVarref; +import pt.up.fe.specs.clava.weaver.enums.LoopKind; import pt.up.fe.specs.clava.weaver.enums.Relation; -import pt.up.fe.specs.util.SpecsEnums; import pt.up.fe.specs.util.lazy.Lazy; import pt.up.fe.specs.util.lazy.ThreadSafeLazy; -import java.util.*; - -public class CxxLoop extends ALoop { +public class CxxLoop> extends ALoop { - private static final Lazy, ALoopKindEnum>> LOOP_TYPE = new ThreadSafeLazy<>( + private static final Lazy, LoopKind>> LOOP_TYPE = new ThreadSafeLazy<>( () -> buildLoopTypeMap()); - private static Map, ALoopKindEnum> buildLoopTypeMap() { - HashMap, ALoopKindEnum> loopTypes = new HashMap<>(); + private static Map, LoopKind> buildLoopTypeMap() { + HashMap, LoopKind> loopTypes = new HashMap<>(); - loopTypes.put(ForStmt.class, ALoopKindEnum.FOR); - loopTypes.put(WhileStmt.class, ALoopKindEnum.WHILE); - loopTypes.put(DoStmt.class, ALoopKindEnum.DOWHILE); - loopTypes.put(CXXForRangeStmt.class, ALoopKindEnum.FOREACH); + loopTypes.put(ForStmt.class, LoopKind.FOR); + loopTypes.put(WhileStmt.class, LoopKind.WHILE); + loopTypes.put(DoStmt.class, LoopKind.DOWHILE); + loopTypes.put(CXXForRangeStmt.class, LoopKind.FOREACH); return loopTypes; } @@ -54,28 +71,29 @@ private static Map, ALoopKindEnum> buildLoopTypeMap() private static final Set VALID_RELATION_OP_SETTER = EnumSet.of(BinaryOperatorKind.GT, BinaryOperatorKind.GE, BinaryOperatorKind.LT, BinaryOperatorKind.LE); - private final LoopStmt loop; - public CxxLoop(LoopStmt loop, CxxWeaver weaver) { - super(new CxxStatement(loop, weaver), weaver); + super(loop, weaver); + } - this.loop = loop; + @Override + public LoopStmt getNodeImpl() { + return (LoopStmt) super.getNodeImpl(); } @Override - public String getKindImpl() { - ALoopKindEnum loopType = LOOP_TYPE.get().get(loop.getClass()); + public LoopKind getKindImpl() { + LoopKind loopType = LOOP_TYPE.get().get(this.getNodeImpl().getClass()); Objects.requireNonNull(loopType, - () -> "Could not determine type of node '" + loop.getClass().getSimpleName() + "'"); + () -> "Could not determine type of node '" + this.getNodeImpl().getClass().getSimpleName() + "'"); - return loopType.name().toLowerCase(); + return loopType; } @Override - public Boolean getIsInnermostImpl() { + public boolean getIsInnermostImpl() { // Loop is innermost if none of its descendants is a loop - Optional anotherLoop = loop.getDescendantsStream() + Optional anotherLoop = this.getNodeImpl().getDescendantsStream() .filter(node -> node instanceof LoopStmt) .findFirst(); @@ -83,9 +101,9 @@ public Boolean getIsInnermostImpl() { } @Override - public Boolean getIsOutermostImpl() { + public boolean getIsOutermostImpl() { // Loop is outermost if none of its ancestors is a loop - Optional anotherLoop = loop.getAscendantsStream() + Optional anotherLoop = this.getNodeImpl().getAscendantsStream() .filter(node -> node instanceof LoopStmt) .findFirst(); @@ -93,9 +111,9 @@ public Boolean getIsOutermostImpl() { } @Override - public Integer getNestedLevelImpl() { + public int getNestedLevelImpl() { // Go back and count how many Loops there are - long parentLoops = loop.getAscendantsStream() + long parentLoops = this.getNodeImpl().getAscendantsStream() .filter(node -> node instanceof LoopStmt) .count(); @@ -103,10 +121,10 @@ public Integer getNestedLevelImpl() { } @Override - public AVarref getControlVarrefImpl() { + public AVarref getControlVarrefImpl() { // Only supported for loops of type 'for' - if (!(loop instanceof ForStmt forStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt forStmt)) { return null; } @@ -114,7 +132,7 @@ public AVarref getControlVarrefImpl() { if (controlVars.isEmpty()) { - ClavaLog.info("Could not find control variable for loop in location: " + loop.getLocation()); + ClavaLog.info("Could not find control variable for loop in location: " + this.getNodeImpl().getLocation()); return null; } @@ -122,7 +140,7 @@ public AVarref getControlVarrefImpl() { if (controlVars.size() > 1) { ClavaLog.info("Found more than one control variable (" + controlVars + ") for loop in location: " - + loop.getLocation()); + + this.getNodeImpl().getLocation()); } return CxxJoinpoints.create(controlVars.get(0), getWeaverEngine(), AVarref.class); @@ -142,8 +160,8 @@ public String getControlVarImpl() { } @Override - public AStatement getCondImpl() { - ClavaNode condition = loop.getStmtCondition().orElse(null); + public AStatement getCondImpl() { + ClavaNode condition = this.getNodeImpl().getStmtCondition().orElse(null); if (condition == null) { return null; @@ -153,12 +171,12 @@ public AStatement getCondImpl() { } @Override - public AStatement getStepImpl() { - if (!(loop instanceof ForStmt)) { + public AStatement getStepImpl() { + if (!(this.getNodeImpl() instanceof ForStmt)) { return null; } - Stmt inc = ((ForStmt) loop).getInc().orElse(null); + Stmt inc = ((ForStmt) this.getNodeImpl()).getInc().orElse(null); if (inc == null) { return null; @@ -168,138 +186,123 @@ public AStatement getStepImpl() { } @Override - public LoopStmt getNode() { - return loop; - } - - @Override - public int[] getRankArrayImpl() { - var rank = loop.getRank(); + public int[] getRankImpl() { + var rank = this.getNodeImpl().getRank(); return rank.stream().mapToInt(Integer::intValue).toArray(); } @Override - public Boolean getIsParallelImpl() { - return loop.isParallel(); + public boolean getIsParallelImpl() { + return this.getNodeImpl().isParallel(); } @Override public Integer getIterationsImpl() { - return loop.getIterations(); + return this.getNodeImpl().getIterations(); } @Override - public void setKindImpl(String kind) { - ALoopKindEnum loopKind = SpecsEnums.valueOf(ALoopKindEnum.class, kind.toUpperCase()); - - if (loopKind == null) { + public void setKindImpl(LoopKind kind) { + if (kind == null) { ClavaLog.warning("Unsupported loop kind:" + kind); return; } - switch (loopKind) { + switch (kind) { case WHILE: convertToWhile(); break; default: - throw new RuntimeException("Not implemented: " + loopKind); + throw new RuntimeException("Not implemented: " + kind); } } private void convertToWhile() { - if (loop instanceof WhileStmt) { + if (this.getNodeImpl() instanceof WhileStmt) { return; } - if (loop instanceof ForStmt) { - - // WhileStmt whileStmt = ClavaNodeFactory.whileStmt(loop.getInfo(), ((ForStmt) loop).getCond().orElse(null), - // loop.getBody().orElse(null)); - - // WhileStmt whileStmt = ClavaNodeFactory.whileStmt(loop.getInfo(), ((ForStmt) loop).getCond().orElse(null), - // loop.getBody()); - Stmt cond = ((ForStmt) loop).getCond().orElse(getWeaverEngine().getFactory().nullStmt()); - WhileStmt whileStmt = getWeaverEngine().getFactory().whileStmt(cond, loop.getBody()); - - replaceWith(CxxJoinpoints.create(whileStmt, getWeaverEngine())); + if (this.getNodeImpl() instanceof ForStmt) { + Stmt cond = ((ForStmt) this.getNodeImpl()).getCond().orElse(getWeaverEngine().getFactory().nullStmt()); + WhileStmt whileStmt = getWeaverEngine().getFactory().whileStmt(cond, this.getNodeImpl().getBody()); + replaceWithImpl(CxxJoinpoints.create(whileStmt, getWeaverEngine())); return; } - throw new RuntimeException("Case not implemented:" + loop.getClass()); - + throw new RuntimeException("Case not implemented:" + this.getNodeImpl().getClass()); } @Override public void setInitImpl(String initCode) { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { return; // TODO: warn user? } var suffix = initCode.strip().endsWith(";") ? "" : ";"; LiteralStmt literalStmt = getFactory().literalStmt(initCode + suffix); - ((ForStmt) loop).setInit(literalStmt); + ((ForStmt) this.getNodeImpl()).setInit(literalStmt); } @Override public void setInitValueImpl(String initCode) { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { return; // TODO: warn user? } Type intType = getWeaverEngine().getFactory().builtinType(BuiltinKind.Int); - ((ForStmt) loop).setInitValue(getWeaverEngine().getFactory().literalExpr(initCode, intType)); + ((ForStmt) this.getNodeImpl()).setInitValue(getWeaverEngine().getFactory().literalExpr(initCode, intType)); } @Override public void setEndValueImpl(String value) { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { return; // TODO: warn user? } Type intType = getWeaverEngine().getFactory().builtinType(BuiltinKind.Int); - ((ForStmt) loop).setConditionValue(getWeaverEngine().getFactory().literalExpr(value, intType)); + ((ForStmt) this.getNodeImpl()).setConditionValue(getWeaverEngine().getFactory().literalExpr(value, intType)); } @Override public void setCondImpl(String condCode) { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { return; // TODO: warn user? } var suffix = condCode.strip().endsWith(";") ? "" : ";"; LiteralStmt literalStmt = getFactory().literalStmt(condCode + suffix); - ((ForStmt) loop).setCond(literalStmt); + ((ForStmt) this.getNodeImpl()).setCond(literalStmt); } @Override public void setStepImpl(String stepCode) { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { return; // TODO: warn user? } LiteralStmt literalStmt = getFactory().literalStmt(stepCode); - ((ForStmt) loop).setInc(literalStmt); + ((ForStmt) this.getNodeImpl()).setInc(literalStmt); } @Override public String getInitValueImpl() { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { ClavaLog.info( "$loop.initValue: Not supported for loops of kind '" + getKindImpl() + "', only 'for' loops."); return null; } - String initValue = ((ForStmt) loop).getInitValueExpr() + String initValue = ((ForStmt) this.getNodeImpl()).getInitValueExpr() .map(ClavaNode::getCode) .orElse(null); @@ -309,64 +312,21 @@ public String getInitValueImpl() { } return initValue; - /* - Optional initOpt = ((ForStmt) loop).getInit(); - - if (initOpt.isPresent()) { - - Stmt init = initOpt.get(); - - ClavaNode child = init.getChild(0); - - if (child instanceof VarDecl) { - - VarDecl decl = (VarDecl) child; - - Optional declInitOpt = decl.getInit(); - if (declInitOpt.isPresent()) { - - return declInitOpt.get().getCode(); - } - } else if (child instanceof BinaryOperator) { - - BinaryOperator binOp = (BinaryOperator) child; - if (binOp.getOp() == BinaryOperatorKind.ASSIGN) { - - return binOp.getRhs().getCode(); - } - } - } - - ClavaLog.warning( - "Could not determine the initial value of the loop. The init statement should be a variable declaration with initialization or assignment."); - return null; - */ } @Override public String getEndValueImpl() { - // Set ops = new HashSet<>(); - // ops.add(BinaryOperatorKind.LE); - // ops.add(BinaryOperatorKind.LT); - // ops.add(BinaryOperatorKind.GE); - // ops.add(BinaryOperatorKind.GT); - // ops.add(BinaryOperatorKind.NE); - - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { ClavaLog.info("Not supported for loops of kind '" + getKindImpl() + "', only 'for' loops (" + getLocationImpl() + ")."); return null; } - ForStmt forLoop = (ForStmt) loop; + ForStmt forLoop = (ForStmt) this.getNodeImpl(); String endValue = forLoop.getConditionValueExpr() .map(ClavaNode::getCode) .orElse(null); - // String endValue = forLoop.getCondOperator() - // .filter(binOp -> ops.contains(binOp.getOp())) - // .map(binOp -> binOp.getRhs().getCode()) - // .orElse(null); if (endValue == null) { ClavaLog.debug( @@ -379,27 +339,33 @@ public String getEndValueImpl() { } @Override - public String getCondRelationImpl() { + public Relation getCondRelationImpl() { BinaryOperator condOp = getConditionOp(); if (condOp == null) { return null; } - // Relation requires lowercase names - var opName = condOp.getOp().name().toLowerCase(); - - var relation = Relation.getHelper().fromNameTry(opName).map(Relation::getString).orElse(null); + // Relation enum constants use the same uppercase names as BinaryOperatorKind + var opName = condOp.getOp().name(); - if (relation == null) { - ClavaLog.warning("Could not map operation with name '" + opName + "' to a Relation. Supported names: " + Relation.getHelper().names()); + // Get Relation with the same name as the operator + Relation relation = null; + try { + relation = Relation.valueOf(opName); + } catch (IllegalArgumentException e) { + var supportedNames = Arrays.stream(Relation.values()) + .map(Relation::name) + .collect(Collectors.joining(", ")); + ClavaLog.warning("Could not map operation with name '" + opName + + "' to a Relation. Supported names: " + supportedNames); } return relation; } @Override - public Boolean getHasCondRelationImpl() { + public boolean getHasCondRelationImpl() { return getConditionOp(false) != null; } @@ -408,7 +374,7 @@ private BinaryOperator getConditionOp() { } private BinaryOperator getConditionOp(boolean showWarnings) { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { if (showWarnings) { ClavaLog.info( "Not supported for loops of kind '" + getKindImpl() + "', only 'for' loops."); @@ -417,7 +383,7 @@ private BinaryOperator getConditionOp(boolean showWarnings) { return null; } - ForStmt forLoop = (ForStmt) loop; + ForStmt forLoop = (ForStmt) this.getNodeImpl(); BinaryOperator binOp = forLoop.getCondOperator().orElse(null); if (binOp == null) { @@ -434,8 +400,8 @@ private BinaryOperator getConditionOp(boolean showWarnings) { } @Override - public void setCondRelationImpl(String operator) { - BinaryOperatorKind kind = BinaryOperatorKind.getHelper().fromValueTry(operator).orElse(null); + public void setCondRelationImpl(Relation operator) { + BinaryOperatorKind kind = BinaryOperatorKind.getHelper().fromValueTry(operator.toString()).orElse(null); if (kind == null) { ClavaLog.info("def 'condRelation': Invalid binary operator " + operator); @@ -458,13 +424,13 @@ public void setCondRelationImpl(String operator) { @Override public String getIdImpl() { - return loop.getLoopId(); + return this.getNodeImpl().getLoopId(); } @Override - public void interchangeImpl(ALoop otherLoop) { + public void interchangeImpl(ALoop otherLoop) { - Optional loopInterchange = LoopInterchange.newInstance(loop, (LoopStmt) otherLoop.getNode()); + Optional loopInterchange = LoopInterchange.newInstance(this.getNodeImpl(), (LoopStmt) otherLoop.getNodeImpl()); if (!loopInterchange.isPresent()) { ClavaLog.info("Could not interchange loops"); return; @@ -474,20 +440,20 @@ public void interchangeImpl(ALoop otherLoop) { } @Override - public Boolean isInterchangeableImpl(ALoop otherLoop) { - return LoopInterchange.test(loop, (LoopStmt) otherLoop.getNode()); + public boolean getIsInterchangeableImpl(ALoop otherLoop) { + return LoopInterchange.test(this.getNodeImpl(), (LoopStmt) otherLoop.getNodeImpl()); } @Override - public AStatement tileImpl(String blockSize, AStatement reference, Boolean useTernary) { + public AStatement tileImpl(String blockSize, AStatement reference, boolean useTernary) { LoopTiling loopTiling = new LoopTiling(getWeaverEngine().getContex()); - boolean success = loopTiling.apply(loop, (Stmt) reference.getNode(), + boolean success = loopTiling.apply(this.getNodeImpl(), (Stmt) reference.getNodeImpl(), blockSize.toString(), useTernary); if (!success) { - ClavaLog.info("Could not tile the loop: " + loop.getLocation()); + ClavaLog.info("Could not tile the loop: " + this.getNodeImpl().getLocation()); } if (loopTiling.getLastReferenceStmt() == null) { @@ -499,19 +465,19 @@ public AStatement tileImpl(String blockSize, AStatement reference, Boolean useTe } @Override - public void setIsParallelImpl(Boolean isParallel) { - loop.setParallel(isParallel); + public void setIsParallelImpl(boolean isParallel) { + this.getNodeImpl().setParallel(isParallel); } @Override - public AExpression getIterationsExprImpl() { - if (!(loop instanceof ForStmt)) { + public AExpression getIterationsExprImpl() { + if (!(this.getNodeImpl() instanceof ForStmt)) { ClavaLog.warning( "Not supported for loops of kind '" + getKindImpl() + "', only 'for' loops."); return null; } - return ((ForStmt) loop).getIterationsExpr() + return ((ForStmt) this.getNodeImpl()).getIterationsExpr() .map(expr -> CxxJoinpoints.create(expr, getWeaverEngine(), AExpression.class)) .orElse(null); @@ -519,13 +485,13 @@ public AExpression getIterationsExprImpl() { @Override public String getStepValueImpl() { - if (!(loop instanceof ForStmt)) { + if (!(this.getNodeImpl() instanceof ForStmt)) { ClavaLog.warning( "Not supported for loops of kind '" + getKindImpl() + "', only 'for' loops."); return null; } - String stepValue = ((ForStmt) loop).getStepValueExpr() + String stepValue = ((ForStmt) this.getNodeImpl()).getStepValueExpr() .map(ClavaNode::getCode) .orElse(null); @@ -538,18 +504,18 @@ public String getStepValueImpl() { } @Override - public AStatement getInitImpl() { + public AStatement getInitImpl() { - if (loop instanceof ForStmt) { - return ((ForStmt) loop).getInit() + if (this.getNodeImpl() instanceof ForStmt) { + return ((ForStmt) this.getNodeImpl()).getInit() .map(init -> CxxJoinpoints.create(init, getWeaverEngine(), AStatement.class)) .orElse(null); } // If range stmt, return begin - if (loop instanceof CXXForRangeStmt) { - return ((CXXForRangeStmt) loop).getBegin() + if (this.getNodeImpl() instanceof CXXForRangeStmt) { + return ((CXXForRangeStmt) this.getNodeImpl()).getBegin() .map(init -> CxxJoinpoints.create(init, getWeaverEngine(), AStatement.class)) .orElse(null); @@ -560,13 +526,13 @@ public AStatement getInitImpl() { } @Override - public AScope getBodyImpl() { - return CxxJoinpoints.create(loop.getBody(), getWeaverEngine(), AScope.class); + public AScope getBodyImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getBody(), getWeaverEngine(), AScope.class); } @Override - public void setBodyImpl(AScope body) { - loop.setBody((CompoundStmt) body.getNode()); + public void setBodyImpl(AScope body) { + this.getNodeImpl().setBody((CompoundStmt) body.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMarker.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMarker.java index f7e174bbcb..b50a7ee945 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMarker.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMarker.java @@ -13,11 +13,8 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import java.util.List; - import com.google.common.base.Preconditions; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.lara.LaraMarkerPragma; import pt.up.fe.specs.clava.ast.stmt.CompoundStmt; import pt.up.fe.specs.clava.weaver.CxxSelects; @@ -26,35 +23,32 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AScope; import pt.up.fe.specs.util.SpecsCollections; -public class CxxMarker extends AMarker { - - private final LaraMarkerPragma marker; +public class CxxMarker> extends AMarker { public CxxMarker(LaraMarkerPragma marker, CxxWeaver weaver) { - super(new CxxPragma(marker, weaver), weaver); - this.marker = marker; + super(marker, weaver); } @Override - public ClavaNode getNode() { - return marker; + public LaraMarkerPragma getNodeImpl() { + return (LaraMarkerPragma) super.getNodeImpl(); } @Override public String getIdImpl() { - return marker.getMarkerId(); + return this.getNodeImpl().getMarkerId(); } @Override - public AScope getContentsImpl() { - List result = CxxSelects.select(getWeaverEngine(), AScope.class, SpecsCollections.toList(marker.getTarget()), + public AScope getContentsImpl() { + AScope[] result = CxxSelects.select(getWeaverEngine(), AScope.class, SpecsCollections.toList(this.getNodeImpl().getTarget()), false, node -> node instanceof CompoundStmt && ((CompoundStmt) node).isNestedScope()); - Preconditions.checkArgument(!result.isEmpty(), - "Could not find the 'scope' associated with the marker '" + marker.getCode() + "'. Pragma target is: " - + marker.getTarget()); - Preconditions.checkArgument(result.size() == 1, "Expected just one scope, but found more than one"); + Preconditions.checkArgument(result.length > 0, + "Could not find the 'scope' associated with the marker '" + this.getNodeImpl().getCode() + "'. Pragma target is: " + + this.getNodeImpl().getTarget()); + Preconditions.checkArgument(result.length == 1, "Expected just one scope, but found more than one"); - return result.get(0); + return result[0]; } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberAccess.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberAccess.java index dbf8e4e0ef..956add16d9 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberAccess.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberAccess.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaNodes; import pt.up.fe.specs.clava.ast.expr.MemberExpr; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -22,55 +21,52 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AMemberAccess; -public class CxxMemberAccess extends AMemberAccess { - - private final MemberExpr memberExpr; +public class CxxMemberAccess> extends AMemberAccess { public CxxMemberAccess(MemberExpr memberExpr, CxxWeaver weaver) { - super(new CxxExpression(memberExpr, weaver), weaver); - this.memberExpr = memberExpr; + super(memberExpr, weaver); } @Override - public ClavaNode getNode() { - return memberExpr; + public MemberExpr getNodeImpl() { + return (MemberExpr) super.getNodeImpl(); } @Override - public AExpression getBaseImpl() { - return CxxJoinpoints.create(ClavaNodes.normalize(memberExpr.getBase()), getWeaverEngine(), AExpression.class); + public AExpression getBaseImpl() { + return CxxJoinpoints.create(ClavaNodes.normalize(this.getNodeImpl().getBase()), getWeaverEngine(), AExpression.class); } @Override public String getNameImpl() { - return memberExpr.getMemberName(); + return this.getNodeImpl().getMemberName(); } @Override - public AExpression[] getMemberChainArrayImpl() { - return memberExpr.getExprChain().stream() + public AExpression[] getMemberChainImpl() { + return this.getNodeImpl().getExprChain().stream() .map(member -> CxxJoinpoints.create(member, getWeaverEngine(), AExpression.class)) .toArray(size -> new AExpression[size]); } @Override - public String[] getMemberChainNamesArrayImpl() { - return memberExpr.getChain().toArray(new String[0]); + public String[] getMemberChainNamesImpl() { + return this.getNodeImpl().getChain().toArray(new String[0]); } @Override - public ADecl getDeclImpl() { - return CxxJoinpoints.create(memberExpr.get(MemberExpr.MEMBER_DECL), getWeaverEngine(), ADecl.class); + public ADecl getDeclImpl() { + return CxxJoinpoints.create(this.getNodeImpl().get(MemberExpr.MEMBER_DECL), getWeaverEngine(), ADecl.class); } @Override - public Boolean getArrowImpl() { - return memberExpr.get(MemberExpr.IS_ARROW); + public boolean getArrowImpl() { + return this.getNodeImpl().get(MemberExpr.IS_ARROW); } @Override - public void setArrowImpl(Boolean isArrow) { - memberExpr.set(MemberExpr.IS_ARROW, isArrow); + public void setArrowImpl(boolean isArrow) { + this.getNodeImpl().set(MemberExpr.IS_ARROW, isArrow); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberCall.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberCall.java index b556a97b20..c23ce52bd0 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberCall.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMemberCall.java @@ -19,28 +19,24 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AMemberCall; -public class CxxMemberCall extends AMemberCall { - - private final CXXMemberCallExpr memberCall; +public class CxxMemberCall> extends AMemberCall { public CxxMemberCall(CXXMemberCallExpr memberCall, CxxWeaver weaver) { - super(new CxxCall(memberCall, weaver), weaver); - - this.memberCall = memberCall; + super(memberCall, weaver); } @Override - public CXXMemberCallExpr getNode() { - return memberCall; + public CXXMemberCallExpr getNodeImpl() { + return (CXXMemberCallExpr) super.getNodeImpl(); } @Override - public AExpression getBaseImpl() { - return CxxJoinpoints.create(memberCall.getBase(), getWeaverEngine(), AExpression.class); + public AExpression getBaseImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getBase(), getWeaverEngine(), AExpression.class); } @Override - public AExpression getRootBaseImpl() { - return CxxJoinpoints.create(memberCall.getRootBase(), getWeaverEngine(), AExpression.class); + public AExpression getRootBaseImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getRootBase(), getWeaverEngine(), AExpression.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMethod.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMethod.java index b3a5c3036d..9a64bef274 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMethod.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxMethod.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.CXXMethodDecl; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; @@ -21,29 +20,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AMethod; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxMethod extends AMethod { - - private final CXXMethodDecl method; +public class CxxMethod> extends AMethod { public CxxMethod(CXXMethodDecl method, CxxWeaver weaver) { - super(new CxxFunction(method, weaver), weaver); - - this.method = method; + super(method, weaver); } @Override - public ClavaNode getNode() { - return method; + public CXXMethodDecl getNodeImpl() { + return (CXXMethodDecl) super.getNodeImpl(); } @Override - public AClass getRecordImpl() { - return method.getRecordDecl().map(record -> CxxJoinpoints.create(record, getWeaverEngine(), AClass.class)).orElse(null); + public AClass getRecordImpl() { + return this.getNodeImpl().getRecordDecl().map(record -> CxxJoinpoints.create(record, getWeaverEngine(), AClass.class)).orElse(null); } @Override public void removeRecordImpl() { - method.removeRecord(); + this.getNodeImpl().removeRecord(); } /** @@ -51,24 +46,13 @@ public void removeRecordImpl() { * this is not required */ @Override - public AType getTypeImpl() { - return CxxJoinpoints.create(method.getReturnType(), getWeaverEngine(), AType.class); + public AType getTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getReturnType(), getWeaverEngine(), AType.class); } @Override - public Boolean getIsVirtualImpl() { - return method.get(CXXMethodDecl.IS_VIRTUAL); + public boolean getIsVirtualImpl() { + return this.getNodeImpl().get(CXXMethodDecl.IS_VIRTUAL); } - /* - @Override - public void defRecordImpl(AClass value) { - method.set(CXXMethodDecl.RECORD, (CXXRecordDecl) value.getNode()); - } - - @Override - public void setRecordImpl(AClass classJp) { - defRecordImpl(classJp); - } - */ } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNamedDecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNamedDecl.java index 724f80e685..fd9df7258a 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNamedDecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNamedDecl.java @@ -24,31 +24,27 @@ import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ANamedDecl; -public class CxxNamedDecl extends ANamedDecl { - - private final NamedDecl namedDecl; +public class CxxNamedDecl> extends ANamedDecl { public CxxNamedDecl(NamedDecl namedDecl, CxxWeaver weaver) { - super(new CxxDecl(namedDecl, weaver), weaver); - - this.namedDecl = namedDecl; + super(namedDecl, weaver); } @Override - public ClavaNode getNode() { - return namedDecl; + public NamedDecl getNodeImpl() { + return (NamedDecl) super.getNodeImpl(); } @Override public String getNameImpl() { - return namedDecl.hasDeclName() ? namedDecl.getDeclName() : null; + return this.getNodeImpl().hasDeclName() ? this.getNodeImpl().getDeclName() : null; } @Override - public Boolean getIsPublicImpl() { + public boolean getIsPublicImpl() { // Search for the first AccessSpecDecl that appears before this node - int declIndex = namedDecl.indexOfSelf(); - List siblings = namedDecl.getParent().getChildren(); + int declIndex = this.getNodeImpl().indexOfSelf(); + List siblings = this.getNodeImpl().getParent().getChildren(); for (int i = declIndex - 1; i >= 0; i--) { if (siblings.get(i) instanceof AccessSpecDecl) { @@ -56,7 +52,7 @@ public Boolean getIsPublicImpl() { } } - boolean isInsideClass = namedDecl.getAncestorTry(RecordDecl.class) + boolean isInsideClass = this.getNodeImpl().getAncestorTry(RecordDecl.class) .map(recordDecl -> recordDecl.get(RecordDecl.TAG_KIND) == TagKind.CLASS) .orElse(false); @@ -66,27 +62,27 @@ public Boolean getIsPublicImpl() { @Override public void setNameImpl(String name) { - namedDecl.set(NamedDecl.DECL_NAME, name); + this.getNodeImpl().set(NamedDecl.DECL_NAME, name); } @Override public String getQualifiedPrefixImpl() { - return namedDecl.get(NamedDecl.QUALIFIED_PREFIX); + return this.getNodeImpl().get(NamedDecl.QUALIFIED_PREFIX); } @Override public String getQualifiedNameImpl() { - return namedDecl.getFullyQualifiedName(); + return this.getNodeImpl().getFullyQualifiedName(); } @Override public void setQualifiedPrefixImpl(String qualifiedPrefix) { - namedDecl.set(NamedDecl.QUALIFIED_PREFIX, qualifiedPrefix); + this.getNodeImpl().set(NamedDecl.QUALIFIED_PREFIX, qualifiedPrefix); } @Override public void setQualifiedNameImpl(String name) { - namedDecl.setQualifiedName(name); + this.getNodeImpl().setQualifiedName(name); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNewExpr.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNewExpr.java index 90297ec113..ca2dad2115 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNewExpr.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxNewExpr.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.CXXNewExpr; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ANewExpr; -public class CxxNewExpr extends ANewExpr { - - private final CXXNewExpr newExpr; +public class CxxNewExpr> extends ANewExpr { public CxxNewExpr(CXXNewExpr newExpr, CxxWeaver weaver) { - super(new CxxExpression(newExpr, weaver), weaver); - this.newExpr = newExpr; + super(newExpr, weaver); } @Override - public ClavaNode getNode() { - return newExpr; + public CXXNewExpr getNodeImpl() { + return (CXXNewExpr) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOmp.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOmp.java index d82f517f06..ea2ea0bb0a 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOmp.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOmp.java @@ -16,7 +16,6 @@ import java.util.Arrays; import java.util.List; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.omp.OmpDirectiveKind; import pt.up.fe.specs.clava.ast.omp.OmpPragma; import pt.up.fe.specs.clava.ast.omp.clauses.OmpClauseKind; @@ -31,70 +30,53 @@ import pt.up.fe.specs.util.SpecsCollections; import pt.up.fe.specs.util.treenode.NodeInsertUtils; -public class CxxOmp extends AOmp { - - private OmpPragma ompPragma; +public class CxxOmp> extends AOmp { public CxxOmp(OmpPragma ompPragma, CxxWeaver weaver) { - super(new CxxPragma(ompPragma, weaver), weaver); - - this.ompPragma = ompPragma; + super(ompPragma, weaver); } @Override - public ClavaNode getNode() { - return ompPragma; + public OmpPragma getNodeImpl() { + return (OmpPragma) super.getNodeImpl(); } @Override public String getKindImpl() { - return ompPragma.getDirectiveKind().getString(); + return this.getNodeImpl().getDirectiveKind().getString(); } @Override public String getNumThreadsImpl() { - return ompPragma.clauses().getNumThreads().orElse(null); + return this.getNodeImpl().clauses().getNumThreads().orElse(null); } @Override public String getProcBindImpl() { - return ompPragma.clauses().getProcBind() + return this.getNodeImpl().clauses().getProcBind() .map(ProcBindKind::getKey) .orElse(null); } @Override - public Boolean hasClauseImpl(String clauseName) { + public boolean getHasClauseImpl(String clauseName) { OmpClauseKind clauseKind = parseClauseName(clauseName); - // if (clauseKind == null) { - // return false; - // } - - return ompPragma.hasClause(clauseKind); + return this.getNodeImpl().hasClause(clauseKind); } private OmpClauseKind parseClauseName(String clauseName) { return OmpClauseKind.getHelper().fromValue(clauseName); - // OmpClauseKind clauseKind = OmpClauseKind.getHelper().valueOfTry(clauseName).orElse(null); - // if (clauseKind == null) { - // - // } - // return clauseKind; } @Override - public Boolean isClauseLegalImpl(String clauseName) { + public boolean getIsClauseLegalImpl(String clauseName) { OmpClauseKind clauseKind = parseClauseName(clauseName); - // if (clauseKind == null) { - // return false; - // } - - return ompPragma.getDirectiveKind().isClauseLegal(clauseKind); + return this.getNodeImpl().getDirectiveKind().isClauseLegal(clauseKind); } @Override public void setNumThreadsImpl(String newExpr) { - ompPragma.clauses().setNumThreads(newExpr); + this.getNodeImpl().clauses().setNumThreads(newExpr); } @Override @@ -102,67 +84,44 @@ public void setProcBindImpl(String newBind) { ProcBindKind kind = ProcBindKind.getHelper().fromValueTry(newBind) .orElseThrow(() -> new RuntimeException("Can't set '" + newBind + "' as a proc bind value, valid values: " + ProcBindKind.getHelper().getAvailableValues())); - ompPragma.clauses().setProcBind(kind); - // ProcBindKind kind = ProcBindKind.getHelper().valueOfTry(newBind).orElse(null); - // if (kind == null) { - // ClavaLog.info("Can't set '" + newBind + "' as a proc bind value, valid values: " - // + ProcBindKind.getHelper().getAvailableOptions()); - // return; - // } - - // setClause(new OmpProcBindClause(kind)); - + this.getNodeImpl().clauses().setProcBind(kind); } - // private void setClause(OmpClause clause) { - // ompPragma.setClause(clause); - // } - @Override - public String[] getPrivateArrayImpl() { - return ompPragma.clauses().getPrivate().toArray(new String[0]); + public String[] getPrivateImpl() { + return this.getNodeImpl().clauses().getPrivate().toArray(new String[0]); } @Override public void setPrivateImpl(String[] newVariables) { - ompPragma.clauses().setPrivate(Arrays.asList(newVariables)); + this.getNodeImpl().clauses().setPrivate(Arrays.asList(newVariables)); } @Override - public String[] getClauseKindsArrayImpl() { - return SpecsCollections.toStringArray(ompPragma.getClauseKinds()); - - // return ompPragma.getClauseKinds().stream() - // .map(OmpClauseKind::getKey) - // .collect(Collectors.toList()) - // .toArray(new String[0]); + public String[] getClauseKindsImpl() { + return SpecsCollections.toStringArray(this.getNodeImpl().getClauseKinds()); } @Override - public String[] getReductionArrayImpl(String kind) { - return ompPragma.clauses().getReduction(kind).toArray(new String[0]); + public String[] getGetReductionImpl(String kind) { + return this.getNodeImpl().clauses().getReduction(kind).toArray(new String[0]); } @Override public void setReductionImpl(String reductionKindString, String[] newVariables) { ReductionKind reductionKind = ReductionKind.getHelper().fromValue(reductionKindString.toLowerCase()); - ompPragma.clauses().setReduction(reductionKind, Arrays.asList(newVariables)); + this.getNodeImpl().clauses().setReduction(reductionKind, Arrays.asList(newVariables)); } @Override - public String[] getReductionKindsArrayImpl() { - return SpecsCollections.toStringArray(ompPragma.clauses().getReductionKinds()); - // String[] a = SpecsCollections.toStringArray(ompPragma.clauses().getReductionKinds()); - // return ompPragma.clauses().getReductionKinds().stream() - // .map(ReductionKind::getKey) - // .collect(Collectors.toList()) - // .toArray(new String[0]); + public String[] getReductionKindsImpl() { + return SpecsCollections.toStringArray(this.getNodeImpl().clauses().getReductionKinds()); } @Override public String getDefaultImpl() { - return ompPragma.clauses().getDefault() + return this.getNodeImpl().clauses().getDefault() .map(DefaultKind::getKey) .orElse(null); } @@ -172,52 +131,52 @@ public void setDefaultImpl(String newDefault) { DefaultKind kind = DefaultKind.getHelper().fromValueTry(newDefault) .orElseThrow(() -> new RuntimeException("Can't set '" + newDefault + "' as a 'default' value, valid values: " + DefaultKind.getHelper().getAvailableValues())); - ompPragma.clauses().setDefault(kind); + this.getNodeImpl().clauses().setDefault(kind); } @Override - public String[] getFirstprivateArrayImpl() { - return ompPragma.clauses().getFirstprivate().toArray(new String[0]); + public String[] getFirstprivateImpl() { + return this.getNodeImpl().clauses().getFirstprivate().toArray(new String[0]); } @Override public void setFirstprivateImpl(String[] newVariables) { - ompPragma.clauses().setFirstprivate(Arrays.asList(newVariables)); + this.getNodeImpl().clauses().setFirstprivate(Arrays.asList(newVariables)); } @Override - public String[] getLastprivateArrayImpl() { - return ompPragma.clauses().getLastprivate().toArray(new String[0]); + public String[] getLastprivateImpl() { + return this.getNodeImpl().clauses().getLastprivate().toArray(new String[0]); } @Override public void setLastprivateImpl(String[] newVariables) { - ompPragma.clauses().setLastprivate(Arrays.asList(newVariables)); + this.getNodeImpl().clauses().setLastprivate(Arrays.asList(newVariables)); } @Override - public String[] getSharedArrayImpl() { - return ompPragma.clauses().getShared().toArray(new String[0]); + public String[] getSharedImpl() { + return this.getNodeImpl().clauses().getShared().toArray(new String[0]); } @Override public void setSharedImpl(String[] newVariables) { - ompPragma.clauses().setShared(Arrays.asList(newVariables)); + this.getNodeImpl().clauses().setShared(Arrays.asList(newVariables)); } @Override - public String[] getCopyinArrayImpl() { - return ompPragma.clauses().getCopyin().toArray(new String[0]); + public String[] getCopyinImpl() { + return this.getNodeImpl().clauses().getCopyin().toArray(new String[0]); } @Override public void setCopyinImpl(String[] newVariables) { - ompPragma.clauses().setCopyin(Arrays.asList(newVariables)); + this.getNodeImpl().clauses().setCopyin(Arrays.asList(newVariables)); } @Override public String getScheduleKindImpl() { - return ompPragma.clauses().getScheduleKind().map(ScheduleKind::getKey).orElse(null); + return this.getNodeImpl().clauses().getScheduleKind().map(ScheduleKind::getKey).orElse(null); } @Override @@ -226,43 +185,43 @@ public void setScheduleKindImpl(String scheduleKindString) { .orElseThrow(() -> new RuntimeException("Can't set '" + scheduleKindString + "' as a schedule kind, valid values: " + ScheduleKind.getHelper().getAvailableValues())); - ompPragma.clauses().setScheduleKind(kind); + this.getNodeImpl().clauses().setScheduleKind(kind); } @Override public String getScheduleChunkSizeImpl() { - return ompPragma.clauses().getScheduleChunkSize().orElse(null); + return this.getNodeImpl().clauses().getScheduleChunkSize().orElse(null); } @Override public void setScheduleChunkSizeImpl(String chunkSize) { - ompPragma.clauses().setScheduleChunkSize(chunkSize); + this.getNodeImpl().clauses().setScheduleChunkSize(chunkSize); } @Override public void setScheduleChunkSizeImpl(int chunkSize) { - setScheduleChunkSize(Integer.toString(chunkSize)); + this.setScheduleChunkSizeImpl(Integer.toString(chunkSize)); } @Override - public String[] getScheduleModifiersArrayImpl() { - return SpecsCollections.toStringArray(ompPragma.clauses().getScheduleModifiers()); + public String[] getScheduleModifiersImpl() { + return SpecsCollections.toStringArray(this.getNodeImpl().clauses().getScheduleModifiers()); } @Override public void setScheduleModifiersImpl(String[] modifiers) { List parsedModifiers = ScheduleModifier.getHelper().fromValue(Arrays.asList(modifiers)); - ompPragma.clauses().setScheduleModifiers(parsedModifiers); + this.getNodeImpl().clauses().setScheduleModifiers(parsedModifiers); } @Override public String getCollapseImpl() { - return ompPragma.clauses().getCollapse().orElse(null); + return this.getNodeImpl().clauses().getCollapse().orElse(null); } @Override public void setCollapseImpl(String newExpr) { - ompPragma.clauses().setCollapse(newExpr); + this.getNodeImpl().clauses().setCollapse(newExpr); } @Override @@ -272,13 +231,12 @@ public void setCollapseImpl(int newExpr) { @Override public String getOrderedImpl() { - return ompPragma.clauses().getOrdered().orElse(null); - + return this.getNodeImpl().clauses().getOrdered().orElse(null); } @Override public void setOrderedImpl(String newExpr) { - ompPragma.clauses().setOrdered(newExpr); + this.getNodeImpl().clauses().setOrdered(newExpr); } @Override @@ -288,7 +246,7 @@ public void removeClauseImpl(String clauseKindString) { + "', name is not valid. Valid clause names: " + OmpClauseKind.getHelper().getAvailableValues())); - ompPragma.removeClause(clauseKind); + this.getNodeImpl().removeClause(clauseKind); } @Override @@ -299,15 +257,12 @@ public void setKindImpl(String directiveKindString) { + OmpDirectiveKind.getHelper().getAvailableValues())); // Create new pragma based on the previous pragma - OmpPragma newOmpPragma = OmpParser.newOmpPragma(directiveKind, ompPragma); + OmpPragma newOmpPragma = OmpParser.newOmpPragma(directiveKind, this.getNodeImpl()); // Replace previous pragma - NodeInsertUtils.replace(ompPragma, newOmpPragma); + NodeInsertUtils.replace(this.getNodeImpl(), newOmpPragma); // Update join point pragma - this.ompPragma = newOmpPragma; - - // Update parent join point - this.aPragma = new CxxPragma(ompPragma, getWeaverEngine()); + this.node = newOmpPragma; } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOp.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOp.java index df08033873..a3c49cb55b 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOp.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxOp.java @@ -13,39 +13,42 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.Operator; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AOp; +import pt.up.fe.specs.clava.weaver.enums.OpKind; -public class CxxOp extends AOp { - - private final Operator op; +public class CxxOp> extends AOp { public CxxOp(Operator op, CxxWeaver weaver) { - super(new CxxExpression(op, weaver), weaver); - - this.op = op; + super(op, weaver); } @Override - public String getKindImpl() { - return op.getKindName(); + public Operator getNodeImpl() { + return (Operator) super.getNodeImpl(); } @Override - public Boolean getIsBitwiseImpl() { - return op.isBitwise(); + public OpKind getKindImpl() { + var op = this.getNodeImpl(); + + try { + return OpKind.fromDisplay(op.getKindName()); + } catch (IllegalArgumentException e) { + throw new RuntimeException("Could not determine operator kind for operator with code '" + op.getOperatorCode() + + "' and kind name '" + op.getKindName() + "'", e); + } } @Override - public ClavaNode getNode() { - return op; + public boolean getIsBitwiseImpl() { + return this.getNodeImpl().isBitwise(); } @Override public String getOperatorImpl() { - return op.getOperatorCode(); + return this.getNodeImpl().getOperatorCode(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParam.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParam.java index 1110c244a9..525518022b 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParam.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParam.java @@ -13,27 +13,23 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.ParmVarDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AParam; -public class CxxParam extends AParam { - - private final ParmVarDecl param; +public class CxxParam> extends AParam { public CxxParam(ParmVarDecl param, CxxWeaver weaver) { - super(new CxxVardecl(param, weaver), weaver); - this.param = param; + super(param, weaver); } @Override - public ClavaNode getNode() { - return param; + public ParmVarDecl getNodeImpl() { + return (ParmVarDecl) super.getNodeImpl(); } @Override - public Boolean getIsParamImpl() { + public boolean getIsParamImpl() { return true; } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParenExpr.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParenExpr.java index b459402baa..10d9e99817 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParenExpr.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxParenExpr.java @@ -13,29 +13,25 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.ParenExpr; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AParenExpr; -public class CxxParenExpr extends AParenExpr { - - private final ParenExpr parenExpr; +public class CxxParenExpr> extends AParenExpr { public CxxParenExpr(ParenExpr parenExpr, CxxWeaver weaver) { - super(new CxxExpression(parenExpr, weaver), weaver); - this.parenExpr = parenExpr; + super(parenExpr, weaver); } @Override - public ClavaNode getNode() { - return parenExpr; + public ParenExpr getNodeImpl() { + return (ParenExpr) super.getNodeImpl(); } @Override - public AExpression getSubExprImpl() { - return CxxJoinpoints.create(parenExpr.getSubExpr(), getWeaverEngine(), AExpression.class); + public AExpression getSubExprImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getSubExpr(), getWeaverEngine(), AExpression.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxPragma.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxPragma.java index 9688d5747a..2c9d02e81e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxPragma.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxPragma.java @@ -12,62 +12,57 @@ */ package pt.up.fe.specs.clava.weaver.joinpoints; - -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.pragma.Pragma; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxSelects; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.APragma; -public class CxxPragma extends APragma { - - private Pragma pragma; +public class CxxPragma> extends APragma { public CxxPragma(Pragma pragma, CxxWeaver weaver) { - super(weaver); - this.pragma = pragma; + super(pragma, weaver); } @Override - public ClavaNode getNode() { - return pragma; + public Pragma getNodeImpl() { + return (Pragma) super.getNodeImpl(); } @Override public String getNameImpl() { - return pragma.getName(); + return this.getNodeImpl().getName(); } @Override - public AJoinPoint getTargetImpl() { - return pragma.getTarget().map(target -> CxxJoinpoints.create(target, - getWeaverEngine(), AJoinPoint.class)).orElse(null); + public AJoinpoint getTargetImpl() { + return this.getNodeImpl().getTarget().map(target -> CxxJoinpoints.create(target, + getWeaverEngine(), AJoinpoint.class)).orElse(null); } @Override public String getContentImpl() { - return pragma.getContent(); + return this.getNodeImpl().getContent(); } @Override public void setContentImpl(String content) { - pragma.setContent(content); + this.getNodeImpl().setContent(content); } @Override public void setNameImpl(String name) { - pragma.setName(name); + this.getNodeImpl().setName(name); } public void setPragma(Pragma pragma) { - this.pragma = pragma; + this.node = pragma; } @Override - public AJoinPoint[] getTargetNodesArrayImpl(String endPragma) { - var pragmaNodes = pragma.getPragmaNodes(endPragma); + public AJoinpoint[] getGetTargetNodesImpl(String endPragma) { + var pragmaNodes = this.getNodeImpl().getPragmaNodes(endPragma); return CxxSelects.selectedNodesToJps(pragmaNodes.stream(), getWeaverEngine()); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxProgram.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxProgram.java index 980895a175..139d5b060a 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxProgram.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxProgram.java @@ -13,7 +13,15 @@ package pt.up.fe.specs.clava.weaver.joinpoints; +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + import org.suikasoft.jOptions.Interfaces.DataStore; + import pt.up.fe.specs.clava.ClavaLog; import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaOptions; @@ -26,41 +34,23 @@ import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFile; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFunction; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AProgram; import pt.up.fe.specs.util.SpecsIo; import pt.up.fe.specs.util.SpecsLogs; -import java.io.File; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -public class CxxProgram extends AProgram { +public class CxxProgram> extends AProgram { private final String name; - private final App app; - // private final File baseFolder; - - // private final List parserOptions; - - // public CxxProgram(File baseFolder, App app, List parserOptions) { - // this.baseFolder = baseFolder; - // this.app = app; - // this.parserOptions = parserOptions; - // } public CxxProgram(App app, CxxWeaver weaver) { - super(weaver); + super(app, weaver); this.name = weaver.getProgramName(); - this.app = app; } @Override - public App getNode() { - return app; + public App getNodeImpl() { + return (App) super.getNodeImpl(); } @Override @@ -81,19 +71,19 @@ public void rebuildFuzzyImpl() { } @Override - public AJoinPoint addFileImpl(AFile file) { - TranslationUnit tu = (TranslationUnit) file.getNode(); - TranslationUnit trueTu = app.addFile(tu); + public AJoinpoint addFileImpl(AFile file) { + TranslationUnit tu = (TranslationUnit) file.getNodeImpl(); + TranslationUnit trueTu = this.getNodeImpl().addFile(tu); if (tu == trueTu) { return file; } - return new CxxFile(trueTu, getWeaverEngine()); + return new CxxFile<>(trueTu, getWeaverEngine()); } @Override - public String[] getIncludeFoldersArrayImpl() { + public String[] getIncludeFoldersImpl() { Set includeFolders = getWeaverEngine().getIncludeFolders(); return includeFolders.toArray(new String[0]); @@ -110,23 +100,17 @@ public String getStdFlagImpl() { } @Override - public String[] getDefaultFlagsArrayImpl() { + public String[] getDefaultFlagsImpl() { return CxxWeaver.getDefaultFlags().toArray(new String[0]); } @Override - public String[] getUserFlagsArrayImpl() { + public String[] getUserFlagsImpl() { return getWeaverEngine().getUserFlags().toArray(new String[0]); } - // @Override - // public void messageToUserImpl(String message) { - // weaver.addMessageToUser(message); - // } - @Override public String getBaseFolderImpl() { - // ClavaLog.deprecated("attribute baseFolder should not be used, instead use file.sourcePath"); List sources = getWeaverEngine().getSources(); if (sources.isEmpty()) { SpecsLogs.warn("Expected at least program to have one source folder, found none"); @@ -139,12 +123,12 @@ public String getBaseFolderImpl() { } public DataStore getAppData() { - return app.getAppData(); + return this.getNodeImpl().getAppData(); } @Override public String getCodeImpl() { - return app.getCode(); + return this.getNodeImpl().getCode(); } @Override @@ -163,74 +147,74 @@ public String getWeavingFolderImpl() { } @Override - public Boolean getIsCxxImpl() { + public boolean getIsCxxImpl() { return getWeaverEngine().getConfig().get(ClavaOptions.STANDARD).isCxx(); } @Override - public String[] getExtraSourcesArrayImpl() { - return app.getExternalDependencies().getExtraSources().stream() + public String[] getExtraSourcesImpl() { + return this.getNodeImpl().getExternalDependencies().getExtraSources().stream() .map(File::getAbsolutePath) .collect(Collectors.toList()) .toArray(new String[0]); } @Override - public String[] getExtraIncludesArrayImpl() { - return app.getExternalDependencies().getExtraIncludes().stream() + public String[] getExtraIncludesImpl() { + return this.getNodeImpl().getExternalDependencies().getExtraIncludes().stream() .map(File::getAbsolutePath) .collect(Collectors.toList()) .toArray(new String[0]); } @Override - public String[] getExtraProjectsArrayImpl() { - return app.getExternalDependencies().getProjects().stream() + public String[] getExtraProjectsImpl() { + return this.getNodeImpl().getExternalDependencies().getProjects().stream() .map(File::getAbsolutePath) .collect(Collectors.toList()) .toArray(new String[0]); } @Override - public String[] getExtraLibsArrayImpl() { + public String[] getExtraLibsImpl() { - return app.getExternalDependencies().getLibs() + return this.getNodeImpl().getExternalDependencies().getLibs() .toArray(new String[0]); } @Override public void addExtraIncludeImpl(String path) { - app.getExternalDependencies().addInclude(new File(path)); + this.getNodeImpl().getExternalDependencies().addInclude(new File(path)); } @Override public void addExtraIncludeFromGitImpl(String gitRepository, String path) { - app.getExternalDependencies().addIncludeFromGit(gitRepository, path); + this.getNodeImpl().getExternalDependencies().addIncludeFromGit(gitRepository, path); } @Override public void addExtraSourceImpl(String path) { - app.getExternalDependencies().addSource(new File(path)); + this.getNodeImpl().getExternalDependencies().addSource(new File(path)); } @Override public void addExtraSourceFromGitImpl(String gitRepository, String path) { - app.getExternalDependencies().addSourceFromGit(gitRepository, path); + this.getNodeImpl().getExternalDependencies().addSourceFromGit(gitRepository, path); } @Override public void addExtraLibImpl(String lib) { - app.getExternalDependencies().addLib(lib); + this.getNodeImpl().getExternalDependencies().addLib(lib); } @Override public void addProjectFromGitImpl(String gitRepo, String[] libs, String path) { - app.getExternalDependencies().addProjectFromGit(gitRepo, Arrays.asList(libs), path); + this.getNodeImpl().getExternalDependencies().addProjectFromGit(gitRepo, Arrays.asList(libs), path); } @Override - public AJoinPoint addFileFromPathImpl(Object filepath) { + public AJoinpoint addFileFromPathImpl(Object filepath) { File file = getFile(filepath); if (!file.isFile()) { @@ -244,7 +228,7 @@ public AJoinPoint addFileFromPathImpl(Object filepath) { // Create file join point TranslationUnit newTu = getFactory().translationUnit(file, Arrays.asList(code)); - return addFileImpl(new CxxFile(newTu, getWeaverEngine())); + return addFileImpl(new CxxFile<>(newTu, getWeaverEngine())); } private File getFile(Object filepath) { @@ -256,22 +240,18 @@ private File getFile(Object filepath) { } @Override - public AFunction getMainImpl() { - for (TranslationUnit tunit : app.getTranslationUnits()) { + public AFunction getMainImpl() { + for (TranslationUnit tunit : this.getNodeImpl().getTranslationUnits()) { for (ClavaNode child : tunit.getChildren()) { - // ClavaLog.debug("getMain: checking if child is FunctionDecl"); if (!(child instanceof FunctionDecl)) { continue; } FunctionDecl function = (FunctionDecl) child; - // ClavaLog.debug("getMain: checking if function is main"); if (!function.getDeclName().toLowerCase().equals("main")) { continue; } - // ClavaLog.debug("getMain: checking if function '" + function.getDeclName() + "' is definition"); - // Calling isDefinition() can be expensive, specially if there are many functions, // testing name first is faster if (!function.isDefinition()) { @@ -283,26 +263,11 @@ public AFunction getMainImpl() { } return null; - /* - // Find main function - return (AFunction) app.getDescendantsStream() - // get functions - .filter(FunctionDecl.class::isInstance) - .map(FunctionDecl.class::cast) - // only definitions - .filter(FunctionDecl::isDefinition) - // the main function - .filter(fdecl -> fdecl.getDeclName().toLowerCase().equals("main")) - .map(CxxJoinpoints::create) - .findFirst() - .orElse(null); - */ } @Override - public void atexitImpl(AFunction function) { - // ClavaLog.debug("Getting main function"); - AFunction mainFunction = getMainImpl(); + public void atexitImpl(AFunction function) { + AFunction mainFunction = getMainImpl(); if (mainFunction == null) { ClavaLog.info("atexit: main() function not found, could not register function"); @@ -314,26 +279,20 @@ public void atexitImpl(AFunction function) { getFactory().builtinType("void")); // Insert call at the beginning of the main function - // ClavaLog.debug("Inserting atexit call at beginning of main"); - mainFunction.getBodyImpl().insertBegin(CxxJoinpoints.create(atexitCall, getWeaverEngine())); + mainFunction.getBodyImpl().insertBeginImpl(CxxJoinpoints.create(atexitCall, getWeaverEngine())); // Add include for atexit - // ClavaLog.debug("Getting file ancestor"); - AFile file = (AFile) mainFunction.getAncestorImpl("file"); - Objects.requireNonNull(file, () -> "Expected main function to be inside a file: " + mainFunction.getNode()); - // ClavaLog.debug("Adding stdlib.h include"); - file.addInclude("stdlib.h", true); + AFile file = (AFile) mainFunction.getGetAncestorImpl("file"); + Objects.requireNonNull(file, () -> "Expected main function to be inside a file: " + mainFunction.getNodeImpl()); + file.addIncludeImpl("stdlib.h", true); // Add include for function - // ClavaLog.debug("Adding function include"); file.addIncludeJpImpl(function); - - // ClavaLog.debug("Finsished"); } @Override - public AFile[] getFilesArrayImpl() { - return app.getTranslationUnits().stream() + public AFile[] getFilesImpl() { + return this.getNodeImpl().getTranslationUnits().stream() .map(tunit -> CxxJoinpoints.create(tunit, getWeaverEngine(), AFile.class)) .collect(Collectors.toList()).toArray(size -> new AFile[size]); diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxRecord.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxRecord.java index 22d03a0693..baf05996a2 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxRecord.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxRecord.java @@ -15,7 +15,6 @@ import java.util.stream.Collectors; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.FieldDecl; import pt.up.fe.specs.clava.ast.decl.RecordDecl; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -24,57 +23,54 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFunction; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ARecord; -public class CxxRecord extends ARecord { - - private final RecordDecl recordDecl; +public class CxxRecord> extends ARecord { public CxxRecord(RecordDecl recordDecl, CxxWeaver weaver) { - super(new CxxNamedDecl(recordDecl, weaver), weaver); - this.recordDecl = recordDecl; + super(recordDecl, weaver); } @Override - public ClavaNode getNode() { - return recordDecl; + public RecordDecl getNodeImpl() { + return (RecordDecl) super.getNodeImpl(); } @Override - public AField[] getFieldsArrayImpl() { - return recordDecl.getFields().stream() + public AField[] getFieldsImpl() { + return this.getNodeImpl().getFields().stream() .map(field -> CxxJoinpoints.create(field, getWeaverEngine(), AField.class)) - .collect(Collectors.toList()).toArray(new AField[0]); + .collect(Collectors.toList()).toArray(AField[]::new); } @Override public String getNameImpl() { - return recordDecl.getDeclName(); + return this.getNodeImpl().getDeclName(); } @Override public String getKindImpl() { - return recordDecl.getTagKind().getCode(); + return this.getNodeImpl().getTagKind().getCode(); } @Override - public AFunction[] getFunctionsArrayImpl() { - return recordDecl.getFunctions().stream() + public AFunction[] getFunctionsImpl() { + return this.getNodeImpl().getFunctions().stream() .map(function -> CxxJoinpoints.create(function, getWeaverEngine(), AFunction.class)) - .toArray(size -> new AFunction[size]); + .toArray(AFunction[]::new); } @Override - public void addFieldImpl(AField field) { - recordDecl.addField((FieldDecl) field.getNode()); + public void addFieldImpl(AField field) { + this.getNodeImpl().addField((FieldDecl) field.getNodeImpl()); } @Override - public Boolean getIsImplementationImpl() { - return recordDecl.isCompleteDefinition(); + public boolean getIsImplementationImpl() { + return this.getNodeImpl().isCompleteDefinition(); } @Override - public Boolean getIsPrototypeImpl() { - return !recordDecl.isCompleteDefinition(); + public boolean getIsPrototypeImpl() { + return !this.getNodeImpl().isCompleteDefinition(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxReturnStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxReturnStmt.java index 51f6f0fbe5..e6230a1b3f 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxReturnStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxReturnStmt.java @@ -13,44 +13,27 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.ReturnStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AReturnStmt; -public class CxxReturnStmt extends AReturnStmt { - - private final ReturnStmt returnStmt; +public class CxxReturnStmt> extends AReturnStmt { public CxxReturnStmt(ReturnStmt returnStmt, CxxWeaver weaver) { - super(new CxxStatement(returnStmt, weaver), weaver); - this.returnStmt = returnStmt; + super(returnStmt, weaver); } @Override - public ClavaNode getNode() { - return returnStmt; + public ReturnStmt getNodeImpl() { + return (ReturnStmt) super.getNodeImpl(); } @Override - public AExpression getReturnExprImpl() { - return returnStmt.getRetValue().map(retValue -> CxxJoinpoints.create(retValue, + public AExpression getReturnExprImpl() { + return this.getNodeImpl().getRetValue().map(retValue -> CxxJoinpoints.create(retValue, getWeaverEngine(), AExpression.class)).orElse(null); } - /* - @Override - public void defReturnExprImpl(AExpression value) { - - // TODO Auto-generated method stub - super.defReturnExprImpl(value); - } - - @Override - public void setReturnExprImpl(AExpression returnExpr) { - defReturnExprImpl(returnExpr); - } - */ } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxScope.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxScope.java index 9bc64ef72b..2fac562db3 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxScope.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxScope.java @@ -14,6 +14,9 @@ package pt.up.fe.specs.clava.weaver.joinpoints; import java.util.List; + +import org.lara.interpreter.weaver.interf.enums.InsertPosition; + import pt.up.fe.specs.clava.ClavaLog; import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaNodes; @@ -30,35 +33,32 @@ import pt.up.fe.specs.clava.weaver.CxxSelects; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.Insert; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AScope; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; import pt.up.fe.specs.clava.weaver.importable.AstFactory; import pt.up.fe.specs.util.SpecsLogs; -public class CxxScope extends AScope { - - private final CompoundStmt scope; +public class CxxScope> extends AScope { public CxxScope(CompoundStmt scope, CxxWeaver weaver) { - super(new CxxStatement(scope, weaver), weaver); - this.scope = scope; + super(scope, weaver); } @Override - public ClavaNode getNode() { - return scope; + public CompoundStmt getNodeImpl() { + return (CompoundStmt) super.getNodeImpl(); } @Override - public AJoinPoint[] insertImpl(String position, String code) { + public AJoinpoint[] insertImpl(InsertPosition position, String code) { // 'body' behaviour - if (!scope.isNestedScope()) { + if (!this.getNodeImpl().isNestedScope()) { Stmt literalStmt = getWeaverEngine().getSnippetParser().parseStmt(code); - CxxActions.insertStmt(position, scope, literalStmt, getWeaverEngine()); - return new AJoinPoint[] { CxxJoinpoints.create(literalStmt, getWeaverEngine()) }; + CxxActions.insertStmt(position, this.getNodeImpl(), literalStmt, getWeaverEngine()); + return new AJoinpoint[] { CxxJoinpoints.create(literalStmt, getWeaverEngine()) }; } // Default behaviour @@ -66,88 +66,88 @@ public AJoinPoint[] insertImpl(String position, String code) { } @Override - public AJoinPoint insertBeforeImpl(AJoinPoint node) { + public AJoinpoint insertBeforeImpl(AJoinpoint node) { // 'body' behaviour - if (!scope.isNestedScope()) { + if (!this.getNodeImpl().isNestedScope()) { ClavaLog.warning("Avoid using action 'insert before' over 'body' joinpoint, use 'insertBegin' instead."); - return insertBodyImplJp("before", node.getNode()); + return insertBodyImplJp(InsertPosition.BEFORE, node.getNodeImpl()); } return super.insertBeforeImpl(node); } @Override - public AJoinPoint insertAfterImpl(AJoinPoint node) { + public AJoinpoint insertAfterImpl(AJoinpoint node) { // 'body' behaviour - if (!scope.isNestedScope()) { + if (!this.getNodeImpl().isNestedScope()) { ClavaLog.warning("Avoid using action 'insert after' over 'body' joinpoint, use 'insertEnd' instead."); - return insertBodyImplJp("after", node.getNode()); + return insertBodyImplJp(InsertPosition.AFTER, node.getNodeImpl()); } return super.insertAfterImpl(node); } @Override - public AJoinPoint replaceWithImpl(AJoinPoint node) { + public AJoinpoint replaceWithImpl(AJoinpoint node) { // 'body' behaviour - if (!scope.isNestedScope() && !(node instanceof AScope)) { + if (!this.getNodeImpl().isNestedScope() && !(node instanceof AScope)) { // Transform, if needed, the given node into a stmt - Stmt stmt = ClavaNodes.toStmt(node.getNode()); - return insertBodyImplJp("replace", stmt); + Stmt stmt = ClavaNodes.toStmt(node.getNodeImpl()); + return insertBodyImplJp(InsertPosition.REPLACE, stmt); } // Default behaviour return super.replaceWithImpl(node); } - private AJoinPoint insertBodyImplJp(String position, ClavaNode newNode) { + private AJoinpoint insertBodyImplJp(InsertPosition position, ClavaNode newNode) { - Stmt newStmt = ClavaNodes.getValidStatement(newNode, Insert.valueOf(position.toUpperCase()).toPosition()); + Stmt newStmt = ClavaNodes.getValidStatement(newNode, Insert.valueOf(position.getDisplay().toUpperCase()).toPosition()); if (newStmt == null) { return null; } - CxxActions.insertStmt(position, scope, newStmt, getWeaverEngine()); + CxxActions.insertStmt(position, this.getNodeImpl(), newStmt, getWeaverEngine()); // Body becomes the parent of this statement return CxxJoinpoints.create(newStmt, getWeaverEngine()); } @Override - public AJoinPoint insertBeginImpl(String code) { + public AJoinpoint insertBeginImpl(String code) { return insertBeginImpl(AstFactory.stmtLiteral(getWeaverEngine(), code)); } @Override - public AJoinPoint insertBeginImpl(AJoinPoint node) { - Stmt newStmt = ClavaNodes.toStmt(node.getNode()); + public AJoinpoint insertBeginImpl(AJoinpoint node) { + Stmt newStmt = ClavaNodes.toStmt(node.getNodeImpl()); - CxxActions.insertStmt("before", scope, newStmt, getWeaverEngine()); + CxxActions.insertStmt(InsertPosition.BEFORE, this.getNodeImpl(), newStmt, getWeaverEngine()); return CxxJoinpoints.create(newStmt, getWeaverEngine()); } @Override - public AJoinPoint insertEndImpl(String code) { + public AJoinpoint insertEndImpl(String code) { return insertEndImpl(AstFactory.stmtLiteral(getWeaverEngine(), code)); } @Override - public AJoinPoint insertEndImpl(AJoinPoint node) { - Stmt newStmt = ClavaNodes.toStmt(node.getNode()); + public AJoinpoint insertEndImpl(AJoinpoint node) { + Stmt newStmt = ClavaNodes.toStmt(node.getNodeImpl()); - CxxActions.insertStmt("after", scope, newStmt, getWeaverEngine()); + CxxActions.insertStmt(InsertPosition.AFTER, this.getNodeImpl(), newStmt, getWeaverEngine()); return CxxJoinpoints.create(newStmt, getWeaverEngine()); } @Override - public Long getNumStatementsImpl(Boolean flat) { - var nodesStream = flat ? scope.getChildrenStream() : scope.getDescendantsStream(); + public long getGetNumStatementsImpl(boolean flat) { + var nodesStream = flat ? this.getNodeImpl().getChildrenStream() : this.getNodeImpl().getDescendantsStream(); return nodesStream.filter(Stmt.class::isInstance) // Ignore CompoundStmt, etc @@ -157,34 +157,34 @@ public Long getNumStatementsImpl(Boolean flat) { } private List getStatements() { - return scope.toStatements(); + return this.getNodeImpl().toStatements(); } @Override public void clearImpl() { - CxxActions.removeChildren(scope, getWeaverEngine()); + CxxActions.removeChildren(this.getNodeImpl(), getWeaverEngine()); } @Override - public Boolean getNakedImpl() { - return scope.isNaked(); + public boolean getNakedImpl() { + return this.getNodeImpl().isNaked(); } @Override - public void setNakedImpl(Boolean isNaked) { - scope.setNaked(isNaked); + public void setNakedImpl(boolean isNaked) { + this.getNodeImpl().setNaked(isNaked); } @Override - public AJoinPoint addLocalImpl(String name, AJoinPoint type, String initValue) { + public AJoinpoint addLocalImpl(String name, AJoinpoint type, String initValue) { // Check if joinpoint is a CxxType if (!(type instanceof AType)) { - SpecsLogs.msgInfo("addLocal: the provided join point (" + type.getJoinPointType() + ") is not a type"); + SpecsLogs.msgInfo("addLocal: the provided join point (" + type.getJoinPointTypeImpl() + ") is not a type"); return null; } - Type typeNode = (Type) type.getNode(); + Type typeNode = (Type) type.getNodeImpl(); // defaults as no init Expr initExpr = null; @@ -199,26 +199,26 @@ public AJoinPoint addLocalImpl(String name, AJoinPoint type, String initValue) { } varDecl.set(VarDecl.IS_USED); - AJoinPoint varDeclJp = CxxJoinpoints.create(varDecl, getWeaverEngine()); + AJoinpoint varDeclJp = CxxJoinpoints.create(varDecl, getWeaverEngine()); - insertBegin(varDeclJp); + insertBeginImpl(varDeclJp); return varDeclJp; } @Override - public AStatement[] getStmtsArrayImpl() { - return CxxJoinpoints.create(getNode().getChildren(Stmt.class), getWeaverEngine(), AStatement.class); + public AStatement[] getStmtsImpl() { + return CxxJoinpoints.create(getNodeImpl().getChildren(Stmt.class), getWeaverEngine(), AStatement.class); } @Override - public AStatement[] getAllStmtsArrayImpl() { - return CxxSelects.select(getWeaverEngine(), AStatement.class, getStatements(), true, CxxSelects::stmtFilter).toArray(new AStatement[0]); + public AStatement[] getAllStmtsImpl() { + return CxxSelects.select(getWeaverEngine(), AStatement.class, getStatements(), true, CxxSelects::stmtFilter); } @Override - public AStatement getFirstStmtImpl() { - AStatement[] stmts = getStmtsArrayImpl(); + public AStatement getFirstStmtImpl() { + AStatement[] stmts = getStmtsImpl(); if (stmts.length == 0) { return null; @@ -229,8 +229,8 @@ public AStatement getFirstStmtImpl() { } @Override - public AStatement getLastStmtImpl() { - AStatement[] stmts = getStmtsArrayImpl(); + public AStatement getLastStmtImpl() { + AStatement[] stmts = getStmtsImpl(); if (stmts.length == 0) { return null; @@ -240,14 +240,14 @@ public AStatement getLastStmtImpl() { } @Override - public AJoinPoint getOwnerImpl() { + public AJoinpoint getOwnerImpl() { // TODO: This should generically work, but corner cases have not been checked return getParentImpl(); } @Override public String cfgImpl() { - ControlFlowGraph cfg = new ControlFlowGraph(scope); + ControlFlowGraph cfg = new ControlFlowGraph(this.getNodeImpl()); var cfgDot = cfg.toDot(); ClavaLog.info(cfgDot); return cfgDot; @@ -255,19 +255,19 @@ public String cfgImpl() { @Override public String dfgImpl() { - DataFlowGraph dfg = new DataFlowGraph(scope); + DataFlowGraph dfg = new DataFlowGraph(this.getNodeImpl()); var dfgDot = dfg.toDot(); ClavaLog.info(dfgDot); return dfgDot; } @Override - public AJoinPoint insertReturnImpl(AJoinPoint code) { + public AJoinpoint insertReturnImpl(AJoinpoint code) { return CxxActions.insertReturn(this, code, getWeaverEngine()); } @Override - public AJoinPoint insertReturnImpl(String code) { + public AJoinpoint insertReturnImpl(String code) { var stmt = CxxJoinpoints.create(getWeaverEngine().getSnippetParser().parseStmt(code), getWeaverEngine()); return insertReturnImpl(stmt); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStatement.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStatement.java index b6e543ddeb..19ea4ecc6d 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStatement.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStatement.java @@ -14,56 +14,47 @@ package pt.up.fe.specs.clava.weaver.joinpoints; import java.util.List; -import pt.up.fe.specs.clava.ClavaNode; + import pt.up.fe.specs.clava.ClavaNodes; import pt.up.fe.specs.clava.ast.stmt.Stmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStatement; import pt.up.fe.specs.util.treenode.NodeInsertUtils; -public class CxxStatement extends AStatement { - - private final Stmt stmt; +public class CxxStatement> extends AStatement { public CxxStatement(Stmt stmt, CxxWeaver weaver) { - super(weaver); - this.stmt = stmt; + super(stmt, weaver); } @Override - public ClavaNode getNode() { - return stmt; + public Stmt getNodeImpl() { + return (Stmt) super.getNodeImpl(); } @Override - public AJoinPoint replaceWithImpl(AJoinPoint node) { + public AJoinpoint replaceWithImpl(AJoinpoint node) { // First "transform" node to insert into a statement - Stmt newStmt = ClavaNodes.toStmt(node.getNode()); + Stmt newStmt = ClavaNodes.toStmt(node.getNodeImpl()); - NodeInsertUtils.replace(stmt, newStmt); + NodeInsertUtils.replace(this.getNodeImpl(), newStmt); // Return a statement joinpoint return CxxJoinpoints.create(newStmt, getWeaverEngine()); } @Override - public Boolean getIsFirstImpl() { + public boolean getIsFirstImpl() { // Get parent and check Stmt position on that list - return stmt.getParent().getChildren(Stmt.class).indexOf(stmt) == 0; - - // return stmt.indexOfSelf() == 1; - // List statementJps = parent.selectStatements(); - // Preconditions.checkArgument(!statementJps.isEmpty(), "Expected parent to "); + return this.getNodeImpl().getParent().getChildren(Stmt.class).indexOf(this.getNodeImpl()) == 0; } @Override - public Boolean getIsLastImpl() { + public boolean getIsLastImpl() { // Get parent and check Stmt position on that list - List siblings = stmt.getParent().getChildren(Stmt.class); - return siblings.indexOf(stmt) == (siblings.size() - 1); - - // return stmt.indexOfSelf() == stmt.getParentImpl().numChildren(); + List siblings = this.getNodeImpl().getParent().getChildren(Stmt.class); + return siblings.indexOf(this.getNodeImpl()) == (siblings.size() - 1); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStruct.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStruct.java index 92c90dfdc2..abdb255675 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStruct.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxStruct.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.RecordDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AStruct; -public class CxxStruct extends AStruct { - - private final RecordDecl recordDecl; +public class CxxStruct> extends AStruct { public CxxStruct(RecordDecl recordDecl, CxxWeaver weaver) { - super(new CxxRecord(recordDecl, weaver), weaver); - this.recordDecl = recordDecl; + super(recordDecl, weaver); } @Override - public ClavaNode getNode() { - return recordDecl; + public RecordDecl getNodeImpl() { + return (RecordDecl) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitch.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitch.java index 5feafd8dcd..cea610cabe 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitch.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitch.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.SwitchStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; @@ -21,41 +20,38 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ASwitch; -public class CxxSwitch extends ASwitch { - - private final SwitchStmt switchStmt; +public class CxxSwitch> extends ASwitch { public CxxSwitch(SwitchStmt switchStmt, CxxWeaver weaver) { - super(new CxxStatement(switchStmt, weaver), weaver); - this.switchStmt = switchStmt; + super(switchStmt, weaver); } @Override - public ClavaNode getNode() { - return switchStmt; + public SwitchStmt getNodeImpl() { + return (SwitchStmt) super.getNodeImpl(); } @Override - public Boolean getHasDefaultCaseImpl() { - return switchStmt.hasDefaultCase(); + public boolean getHasDefaultCaseImpl() { + return this.getNodeImpl().hasDefaultCase(); } @Override - public ACase getGetDefaultCaseImpl() { - return switchStmt.getDefaultCase() + public ACase getGetDefaultCaseImpl() { + return this.getNodeImpl().getDefaultCase() .map(node -> CxxJoinpoints.create(node, getWeaverEngine(), ACase.class)) .orElse(null); } @Override - public ACase[] getCasesArrayImpl() { - return CxxJoinpoints.create(switchStmt.getCases(), getWeaverEngine(), ACase.class); + public ACase[] getCasesImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getCases(), getWeaverEngine(), ACase.class); } @Override - public AExpression getConditionImpl() { - return CxxJoinpoints.create(switchStmt.getCond(), getWeaverEngine(), AExpression.class); + public AExpression getConditionImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getCond(), getWeaverEngine(), AExpression.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitchCase.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitchCase.java index 52a86d3c92..73a4cd6dc3 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitchCase.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxSwitchCase.java @@ -1,22 +1,18 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.stmt.SwitchCase; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ASwitchCase; -public class CxxSwitchCase extends ASwitchCase { - - private final SwitchCase switchCase; +public class CxxSwitchCase> extends ASwitchCase { public CxxSwitchCase(SwitchCase switchCase, CxxWeaver weaver) { - super(new CxxStatement(switchCase, weaver), weaver); - this.switchCase = switchCase; + super(switchCase, weaver); } @Override - public ClavaNode getNode() { - return switchCase; + public SwitchCase getNodeImpl() { + return (SwitchCase) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTag.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTag.java index 0f3775652c..7f9cd1c341 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTag.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTag.java @@ -13,39 +13,37 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; +import org.lara.interpreter.weaver.interf.enums.InsertPosition; + import pt.up.fe.specs.clava.ast.lara.LaraTagPragma; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.Insert; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATag; -public class CxxTag extends ATag { - - private final LaraTagPragma tag; +public class CxxTag> extends ATag { public CxxTag(LaraTagPragma reference, CxxWeaver weaver) { - super(new CxxPragma(reference, weaver), weaver); - tag = reference; + super(reference, weaver); } @Override - public ClavaNode getNode() { - return tag; + public LaraTagPragma getNodeImpl() { + return (LaraTagPragma) super.getNodeImpl(); } @Override public String getIdImpl() { - return tag.getTagId(); + return this.getNodeImpl().getTagId(); } @Override - public AJoinPoint[] insertImpl(String position, String code) { + public AJoinpoint[] insertImpl(InsertPosition position, String code) { - Insert insert = Insert.getHelper().fromValue(position); + Insert insert = Insert.getHelper().fromValue(position.getDisplay()); if (insert == Insert.AFTER) { - return (AJoinPoint[]) getTargetImpl().insertImpl(position, code); + return (AJoinpoint[]) getTargetImpl().insertImpl(position, code); } else { return super.insertImpl(position, code); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTernaryOp.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTernaryOp.java index 7335642aa5..86a98275a0 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTernaryOp.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTernaryOp.java @@ -13,40 +13,35 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.ConditionalOperator; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATernaryOp; -public class CxxTernaryOp extends ATernaryOp { - - private final ConditionalOperator op; +public class CxxTernaryOp> extends ATernaryOp { public CxxTernaryOp(ConditionalOperator op, CxxWeaver weaver) { - super(new CxxOp(op, weaver), weaver); - - this.op = op; + super(op, weaver); } @Override - public ClavaNode getNode() { - return op; + public ConditionalOperator getNodeImpl() { + return (ConditionalOperator) super.getNodeImpl(); } @Override - public AExpression getCondImpl() { - return CxxJoinpoints.create(op.getCondition(), getWeaverEngine(), AExpression.class); + public AExpression getCondImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getCondition(), getWeaverEngine(), AExpression.class); } @Override - public AExpression getTrueExprImpl() { - return CxxJoinpoints.create(op.getTrueExpr(), getWeaverEngine(), AExpression.class); + public AExpression getTrueExprImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getTrueExpr(), getWeaverEngine(), AExpression.class); } @Override - public AExpression getFalseExprImpl() { - return CxxJoinpoints.create(op.getFalseExpr(), getWeaverEngine(), AExpression.class); + public AExpression getFalseExprImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getFalseExpr(), getWeaverEngine(), AExpression.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxThis.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxThis.java index f0017c2166..cd6e03e1f5 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxThis.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxThis.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.CXXThisExpr; import pt.up.fe.specs.clava.ast.type.TagType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -22,34 +21,31 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.APointerType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AThis; -public class CxxThis extends AThis { - - private final CXXThisExpr thisExpr; +public class CxxThis> extends AThis { public CxxThis(CXXThisExpr thisExpr, CxxWeaver weaver) { - super(new CxxExpression(thisExpr, weaver), weaver); - this.thisExpr = thisExpr; + super(thisExpr, weaver); } @Override - public ClavaNode getNode() { - return thisExpr; + public CXXThisExpr getNodeImpl() { + return (CXXThisExpr) super.getNodeImpl(); } @Override - public ADecl getDeclImpl() { + public ADecl getDeclImpl() { // type.pointee.decl var type = getTypeImpl(); if (!(type instanceof APointerType)) { - throw new RuntimeException("Not implemented with type is " + type.getJoinPointType()); + throw new RuntimeException("Not implemented with type is " + type.getJoinPointTypeImpl()); } // Get class type - var pointeeType = ((APointerType) type).getPointeeImpl(); + var pointeeType = ((APointerType) type).getPointeeImpl(); - var thisType = pointeeType.getNode(); + var thisType = pointeeType.getNodeImpl(); if (!(thisType instanceof TagType)) { throw new RuntimeException("Not implemented when this type is a " + thisType.getClass()); diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefDecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefDecl.java index 1b4c9bf216..d23da45633 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefDecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefDecl.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.TypedefDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATypedefDecl; -public class CxxTypedefDecl extends ATypedefDecl { - - private final TypedefDecl typedefDecl; +public class CxxTypedefDecl> extends ATypedefDecl { public CxxTypedefDecl(TypedefDecl typedefDecl, CxxWeaver weaver) { - super(new CxxTypedefNameDecl(typedefDecl, weaver), weaver); - this.typedefDecl = typedefDecl; + super(typedefDecl, weaver); } @Override - public ClavaNode getNode() { - return typedefDecl; + public TypedefDecl getNodeImpl() { + return (TypedefDecl) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefNameDecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefNameDecl.java index 832ba2063c..6232b1bfe4 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefNameDecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxTypedefNameDecl.java @@ -13,23 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.TypedefNameDecl; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATypedefNameDecl; -public class CxxTypedefNameDecl extends ATypedefNameDecl { - - private final TypedefNameDecl typedefNameDecl; +public class CxxTypedefNameDecl> extends ATypedefNameDecl { public CxxTypedefNameDecl(TypedefNameDecl typedefNameDecl, CxxWeaver weaver) { - super(new CxxNamedDecl(typedefNameDecl, weaver), weaver); - this.typedefNameDecl = typedefNameDecl; + super(typedefNameDecl, weaver); } @Override - public ClavaNode getNode() { - return typedefNameDecl; + public TypedefNameDecl getNodeImpl() { + return (TypedefNameDecl) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryExprOrType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryExprOrType.java index 6baddf1182..c86cf26d2d 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryExprOrType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryExprOrType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.UnaryExprOrTypeTraitExpr; import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -23,33 +22,31 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AUnaryExprOrType; import pt.up.fe.specs.util.SpecsLogs; -public class CxxUnaryExprOrType extends AUnaryExprOrType { - - private final UnaryExprOrTypeTraitExpr expr; +public class CxxUnaryExprOrType> extends AUnaryExprOrType { public CxxUnaryExprOrType(UnaryExprOrTypeTraitExpr expr, CxxWeaver weaver) { - super(new CxxExpression(expr, weaver), weaver); - - this.expr = expr; + super(expr, weaver); } @Override - public ClavaNode getNode() { - return expr; + public UnaryExprOrTypeTraitExpr getNodeImpl() { + return (UnaryExprOrTypeTraitExpr) super.getNodeImpl(); } @Override - public Boolean getHasTypeExprImpl() { - return expr.hasTypeExpression(); + public boolean getHasTypeExprImpl() { + return this.getNodeImpl().hasTypeExpression(); } @Override - public Boolean getHasArgExprImpl() { - return expr.hasArgumentExpression(); + public boolean getHasArgExprImpl() { + return this.getNodeImpl().hasArgumentExpression(); } @Override - public AType getArgTypeImpl() { + public AType getArgTypeImpl() { + var expr = this.getNodeImpl(); + if (!expr.hasTypeExpression()) { return null; } @@ -58,7 +55,9 @@ public AType getArgTypeImpl() { } @Override - public AExpression getArgExprImpl() { + public AExpression getArgExprImpl() { + var expr = this.getNodeImpl(); + if (!expr.hasArgumentExpression()) { return null; } @@ -67,17 +66,19 @@ public AExpression getArgExprImpl() { } @Override - public void setArgTypeImpl(AType argType) { + public void setArgTypeImpl(AType argType) { + var expr = this.getNodeImpl(); + if (!expr.hasTypeExpression()) { SpecsLogs.msgInfo("UnaryExprOrType '" + expr.getUettKind() + "' does not have a type argument"); return; } - expr.setArgType((Type) argType.getNode()); + expr.setArgType((Type) argType.getNodeImpl()); } @Override public String getKindImpl() { - return expr.getUettKind().getString(); + return this.getNodeImpl().getUettKind().getString(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryOp.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryOp.java index 3eeb49fdf0..8822953268 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryOp.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxUnaryOp.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ClavaNodes; import pt.up.fe.specs.clava.ast.expr.UnaryOperator; import pt.up.fe.specs.clava.ast.expr.enums.UnaryOperatorKind; @@ -22,33 +21,30 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AUnaryOp; -public class CxxUnaryOp extends AUnaryOp { - - private final UnaryOperator unaryOp; +public class CxxUnaryOp> extends AUnaryOp { public CxxUnaryOp(UnaryOperator unaryOp, CxxWeaver weaver) { - super(new CxxOp(unaryOp, weaver), weaver); - this.unaryOp = unaryOp; + super(unaryOp, weaver); } @Override - public ClavaNode getNode() { - return unaryOp; + public UnaryOperator getNodeImpl() { + return (UnaryOperator) super.getNodeImpl(); } @Override - public AExpression getOperandImpl() { - return CxxJoinpoints.create(ClavaNodes.normalize(unaryOp.getSubExpr()), getWeaverEngine(), AExpression.class); + public AExpression getOperandImpl() { + return CxxJoinpoints.create(ClavaNodes.normalize(this.getNodeImpl().getSubExpr()), getWeaverEngine(), AExpression.class); } @Override - public Boolean getIsPointerDerefImpl() { - return unaryOp.getOp() == UnaryOperatorKind.Deref; + public boolean getIsPointerDerefImpl() { + return this.getNodeImpl().getOp() == UnaryOperatorKind.Deref; } @Override - public Boolean getIsBitwiseImpl() { - return unaryOp.getOp().isBitwise(); + public boolean getIsBitwiseImpl() { + return this.getNodeImpl().getOp().isBitwise(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVardecl.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVardecl.java index 7e310f6278..6cdda2ca33 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVardecl.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVardecl.java @@ -13,7 +13,9 @@ package pt.up.fe.specs.clava.weaver.joinpoints; -import pt.up.fe.specs.clava.ClavaNode; +import java.util.HashMap; +import java.util.Map; + import pt.up.fe.specs.clava.ast.decl.VarDecl; import pt.up.fe.specs.clava.ast.expr.Expr; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,39 +23,54 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVardecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVarref; +import pt.up.fe.specs.clava.weaver.enums.StorageClass; import pt.up.fe.specs.clava.weaver.importable.AstFactory; +import pt.up.fe.specs.util.lazy.Lazy; +import pt.up.fe.specs.util.lazy.ThreadSafeLazy; -public class CxxVardecl extends AVardecl { +public class CxxVardecl> extends AVardecl { - private final VarDecl varDecl; + private static final Lazy> STORAGE_TYPE = new ThreadSafeLazy<>( + () -> buildStorageTypeMap()); - public CxxVardecl(VarDecl varDecl, CxxWeaver weaver) { - super(new CxxDeclarator(varDecl, weaver), weaver); + private static Map buildStorageTypeMap() { + HashMap storageClasses = new HashMap<>(); + + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.None, StorageClass.NONE); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Extern, StorageClass.EXTERN); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Static, StorageClass.STATIC); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.PrivateExtern, StorageClass.PRIVATE_EXTERN); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Auto, StorageClass.AUTO); + storageClasses.put(pt.up.fe.specs.clava.ast.decl.enums.StorageClass.Register, StorageClass.REGISTER); - this.varDecl = varDecl; + return storageClasses; + } + + public CxxVardecl(VarDecl varDecl, CxxWeaver weaver) { + super(varDecl, weaver); } @Override - public ClavaNode getNode() { - return varDecl; + public VarDecl getNodeImpl() { + return (VarDecl) super.getNodeImpl(); } @Override - public Boolean getHasInitImpl() { - return varDecl.getInit().isPresent(); + public boolean getHasInitImpl() { + return this.getNodeImpl().getInit().isPresent(); } @Override - public AExpression getInitImpl() { - return varDecl.getInit().map(init -> (AExpression) CxxJoinpoints.create(init, getWeaverEngine())).orElse(null); + public AExpression getInitImpl() { + return this.getNodeImpl().getInit().map(init -> (AExpression) CxxJoinpoints.create(init, getWeaverEngine())).orElse(null); } @Override - public void setInitImpl(AExpression init) { + public void setInitImpl(AExpression init) { if (init == null) { removeInitImpl(true); } else { - varDecl.setInit((Expr) init.getNode()); + this.getNodeImpl().setInit((Expr) init.getNodeImpl()); } } @@ -63,53 +80,65 @@ public void setInitImpl(String init) { removeInitImpl(true); } - varDecl.setInit(getWeaverEngine().getFactory().literalExpr(init, varDecl.getType())); + this.getNodeImpl().setInit(getWeaverEngine().getFactory().literalExpr(init, this.getNodeImpl().getType())); } @Override public void removeInitImpl(boolean removeConst) { - varDecl.removeInit(removeConst); + this.getNodeImpl().removeInit(removeConst); } @Override - public Boolean getIsParamImpl() { + public boolean getIsParamImpl() { return false; } @Override - public String getStorageClassImpl() { - return varDecl.get(VarDecl.STORAGE_CLASS).getString(); + public StorageClass getStorageClassImpl() { + var nodeStorageClass = this.getNodeImpl().get(VarDecl.STORAGE_CLASS); + if (nodeStorageClass == null) { + throw new RuntimeException("Storage class of variable '" + getNameImpl() + "' is null"); + } + + StorageClass jpStorageClass = STORAGE_TYPE.get().get(nodeStorageClass); + if (jpStorageClass == null) { + throw new RuntimeException("Storage class '" + nodeStorageClass + "' of variable '" + getNameImpl() + + "' is not supported in the join point model"); + } + + return jpStorageClass; } @Override - public void setStorageClassImpl(String storageClass) { - varDecl.setStorageClass(storageClass); + public void setStorageClassImpl(StorageClass storageClass) { + var nodeStorageClass = STORAGE_TYPE.get().entrySet().stream() + .filter(entry -> entry.getValue() == storageClass) + .map(Map.Entry::getKey) + .findFirst() + .orElseThrow(() -> new RuntimeException( + "Storage class '" + storageClass + "' is not supported in the join point model")); + + this.getNodeImpl().setStorageClass(nodeStorageClass); } @Override - public Boolean getIsGlobalImpl() { - return varDecl.get(VarDecl.HAS_GLOBAL_STORAGE); + public boolean getIsGlobalImpl() { + return this.getNodeImpl().get(VarDecl.HAS_GLOBAL_STORAGE); } @Override public String getInitStyleImpl() { - return varDecl.get(VarDecl.INIT_STYLE).getString(); - // return InitializationStyle.valueOf(varDecl.get(VarDecl.INIT_STYLE).name()); + return this.getNodeImpl().get(VarDecl.INIT_STYLE).getString(); } @Override - public AVardecl getDefinitionImpl() { - return CxxJoinpoints.create(varDecl.getDefinition(), getWeaverEngine(), AVardecl.class); + public AVardecl getDefinitionImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getDefinition(), getWeaverEngine(), AVardecl.class); } - // @Override - // public void varrefImpl() { - // return CxxJoinpoints.create(AstFactory.varref(CxxJoinpoints.create(varDecl, AVardecl.class), AVarref.class)); - // } - @Override - public AVarref varrefImpl() { - return AstFactory.varref(getWeaverEngine(), CxxJoinpoints.create(varDecl, getWeaverEngine(), AVardecl.class)); + public AVarref varrefImpl() { + return AstFactory.varref(getWeaverEngine(), CxxJoinpoints.create(this.getNodeImpl(), getWeaverEngine(), AVardecl.class)); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVarref.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVarref.java index 34bb208124..ff38c655b6 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVarref.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxVarref.java @@ -26,56 +26,52 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVardecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVarref; -public class CxxVarref extends AVarref { - - private final DeclRefExpr refExpr; +public class CxxVarref> extends AVarref { public CxxVarref(DeclRefExpr refExpr, CxxWeaver weaver) { - super(new CxxExpression(refExpr, weaver), weaver); - - this.refExpr = refExpr; + super(refExpr, weaver); } @Override - public DeclRefExpr getNode() { - return refExpr; + public DeclRefExpr getNodeImpl() { + return (DeclRefExpr) super.getNodeImpl(); } @Override public String getNameImpl() { - return refExpr.getRefName(); + return this.getNodeImpl().getRefName(); } @Override public void setNameImpl(String name) { - refExpr.setRefName(name); + this.getNodeImpl().setRefName(name); } @Override public String getKindImpl() { - return refExpr.getKind().name().toLowerCase(); + return this.getNodeImpl().getKind().name().toLowerCase(); } @Override - public AExpression getUseExprImpl() { - return CxxJoinpoints.create(refExpr.getUseExpr(), getWeaverEngine(), AExpression.class); + public AExpression getUseExprImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getUseExpr(), getWeaverEngine(), AExpression.class); } @Override - public AVardecl getVardeclImpl() { - ADeclarator declarator = getDeclarationImpl(); + public AVardecl getVardeclImpl() { + ADeclarator declarator = getDeclarationImpl(); - return declarator instanceof AVardecl ? (AVardecl) declarator : null; + return declarator instanceof AVardecl ? (AVardecl) declarator : null; } @Override - public Boolean getIsFunctionCallImpl() { - return refExpr.isFunctionCall(); + public boolean getIsFunctionCallImpl() { + return this.getNodeImpl().isFunctionCall(); } @Override - public ADeclarator getDeclarationImpl() { - Optional declarator = refExpr.getVariableDeclaration(); + public ADeclarator getDeclarationImpl() { + Optional declarator = this.getNodeImpl().getVariableDeclaration(); if (!declarator.isPresent()) { return null; @@ -85,13 +81,13 @@ public ADeclarator getDeclarationImpl() { } @Override - public ADecl getDeclImpl() { + public ADecl getDeclImpl() { return getVardeclImpl(); } @Override public String getPropertyImpl() { - var parent = refExpr.getParent(); + var parent = this.getNodeImpl().getParent(); if (parent == null) { return null; @@ -105,13 +101,13 @@ public String getPropertyImpl() { } @Override - public Boolean getHasPropertyImpl() { - if (!refExpr.hasParent()) { + public boolean getHasPropertyImpl() { + if (!this.getNodeImpl().hasParent()) { return false; } // If parent is a MSPropertyRefExpr, this this varref has a MS-style property - return refExpr.getParent() instanceof MSPropertyRefExpr; + return this.getNodeImpl().getParent() instanceof MSPropertyRefExpr; } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxWrapperStmt.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxWrapperStmt.java index 72ad3a2e8d..dc2043a911 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxWrapperStmt.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/CxxWrapperStmt.java @@ -19,43 +19,40 @@ import pt.up.fe.specs.clava.ast.stmt.WrapperStmt; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AWrapperStmt; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.enums.AWrapperStmtKindEnum; +import pt.up.fe.specs.clava.weaver.enums.WrapperStatementKind; -public class CxxWrapperStmt extends AWrapperStmt { - - private final WrapperStmt wrapperStmt; +public class CxxWrapperStmt> extends AWrapperStmt { public CxxWrapperStmt(WrapperStmt wrapperStmt, CxxWeaver weaver) { - super(new CxxStatement(wrapperStmt, weaver), weaver); - this.wrapperStmt = wrapperStmt; + super(wrapperStmt, weaver); } @Override - public ClavaNode getNode() { - return wrapperStmt; + public WrapperStmt getNodeImpl() { + return (WrapperStmt) super.getNodeImpl(); } @Override - public String getKindImpl() { + public WrapperStatementKind getKindImpl() { - ClavaNode wrappedNode = wrapperStmt.getWrappedNode(); + ClavaNode wrappedNode = this.getNodeImpl().getWrappedNode(); if (wrappedNode instanceof Comment) { - return AWrapperStmtKindEnum.COMMENT.getName(); + return WrapperStatementKind.COMMENT; } if (wrappedNode instanceof Pragma) { - return AWrapperStmtKindEnum.PRAGMA.getName(); + return WrapperStatementKind.PRAGMA; } throw new RuntimeException("Case not defined for wrapperStmt.kind: " + wrappedNode.getClass().getSimpleName()); } @Override - public AJoinPoint getContentImpl() { - return CxxJoinpoints.create(wrapperStmt.getWrappedNode(), getWeaverEngine()); + public AJoinpoint getContentImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getWrappedNode(), getWeaverEngine()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkFor.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkFor.java index b935abee78..a65ff74da2 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkFor.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkFor.java @@ -13,25 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints.cilk; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.cilk.CilkFor; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ACilkFor; -import pt.up.fe.specs.clava.weaver.joinpoints.CxxLoop; -public class CxxCilkFor extends ACilkFor { - - private final CilkFor loop; +public class CxxCilkFor> extends ACilkFor { public CxxCilkFor(CilkFor loop, CxxWeaver weaver) { - super(new CxxLoop(loop, weaver), weaver); - - this.loop = loop; + super(loop, weaver); } @Override - public ClavaNode getNode() { - return loop; + public CilkFor getNodeImpl() { + return (CilkFor) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSpawn.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSpawn.java index 294e7ca369..6563a0003d 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSpawn.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSpawn.java @@ -13,25 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints.cilk; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.cilk.CilkSpawn; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ACilkSpawn; -import pt.up.fe.specs.clava.weaver.joinpoints.CxxCall; -public class CxxCilkSpawn extends ACilkSpawn { - - private final CilkSpawn spawnCall; +public class CxxCilkSpawn> extends ACilkSpawn { public CxxCilkSpawn(CilkSpawn spawnCall, CxxWeaver weaver) { - super(new CxxCall(spawnCall, weaver), weaver); - - this.spawnCall = spawnCall; + super(spawnCall, weaver); } @Override - public ClavaNode getNode() { - return spawnCall; + public CilkSpawn getNodeImpl() { + return (CilkSpawn) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSync.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSync.java index 0f66786db5..d170cb358c 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSync.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/cilk/CxxCilkSync.java @@ -13,24 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints.cilk; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.cilk.CilkSync; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ACilkSync; -import pt.up.fe.specs.clava.weaver.joinpoints.CxxStatement; -public class CxxCilkSync extends ACilkSync { - - private final CilkSync cilkSync; +public class CxxCilkSync> extends ACilkSync { public CxxCilkSync(CilkSync cilkSync, CxxWeaver weaver) { - super(new CxxStatement(cilkSync, weaver), weaver); - this.cilkSync = cilkSync; + super(cilkSync, weaver); } @Override - public ClavaNode getNode() { - return cilkSync; + public CilkSync getNodeImpl() { + return (CilkSync) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxAdjustedType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxAdjustedType.java index db1b8f34c2..4a0cd5faab 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxAdjustedType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxAdjustedType.java @@ -13,40 +13,35 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.AdjustedType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AAdjustedType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxAdjustedType extends AAdjustedType { - - private final AdjustedType adjustedType; +public class CxxAdjustedType> extends AAdjustedType { public CxxAdjustedType(AdjustedType adjustedType, CxxWeaver weaver) { - super(new CxxType(adjustedType, weaver), weaver); - - this.adjustedType = adjustedType; + super(adjustedType, weaver); } @Override - public ClavaNode getNode() { - return adjustedType; + public AdjustedType getNodeImpl() { + return (AdjustedType) super.getNodeImpl(); } @Override - public AType getOriginalTypeImpl() { - return CxxJoinpoints.create(adjustedType.get(AdjustedType.ORIGINAL_TYPE), getWeaverEngine(), AType.class); + public AType getOriginalTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().get(AdjustedType.ORIGINAL_TYPE), getWeaverEngine(), AType.class); } @Override - public int[] getArrayDimsArrayImpl() { - return getOriginalTypeImpl().getArrayDimsArrayImpl(); + public int[] getArrayDimsImpl() { + return getOriginalTypeImpl().getArrayDimsImpl(); } @Override - public Integer getArraySizeImpl() { + public int getArraySizeImpl() { return getOriginalTypeImpl().getArraySizeImpl(); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxArrayType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxArrayType.java index b1c3ae53b2..8600bf3136 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxArrayType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxArrayType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.ArrayType; import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,29 +20,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AArrayType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxArrayType extends AArrayType { - - private final ArrayType arrayType; +public class CxxArrayType> extends AArrayType { public CxxArrayType(ArrayType arrayType, CxxWeaver weaver) { - super(new CxxType(arrayType, weaver), weaver); - - this.arrayType = arrayType; + super(arrayType, weaver); } @Override - public ClavaNode getNode() { - return arrayType; + public ArrayType getNodeImpl() { + return (ArrayType) super.getNodeImpl(); } @Override - public AType getElementTypeImpl() { - return CxxJoinpoints.create(arrayType.getElementType(), getWeaverEngine(), AType.class); + public AType getElementTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getElementType(), getWeaverEngine(), AType.class); } @Override - public void setElementTypeImpl(AType arrayElementType) { - arrayType.setElementType((Type) arrayElementType.getNode()); + public void setElementTypeImpl(AType arrayElementType) { + this.getNodeImpl().setElementType((Type) arrayElementType.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxBuiltinType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxBuiltinType.java index 323de90caa..e42e40bf46 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxBuiltinType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxBuiltinType.java @@ -13,54 +13,49 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.BuiltinType; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ABuiltinType; -public class CxxBuiltinType extends ABuiltinType { - - private final BuiltinType builtinType; +public class CxxBuiltinType> extends ABuiltinType { public CxxBuiltinType(BuiltinType builtinType, CxxWeaver weaver) { - super(new CxxType(builtinType, weaver), weaver); - - this.builtinType = builtinType; + super(builtinType, weaver); } @Override - public ClavaNode getNode() { - return builtinType; + public BuiltinType getNodeImpl() { + return (BuiltinType) super.getNodeImpl(); } @Override public String getBuiltinKindImpl() { - return builtinType.get(BuiltinType.KIND).name(); + return this.getNodeImpl().get(BuiltinType.KIND).name(); } @Override - public Boolean getIsIntegerImpl() { - return builtinType.get(BuiltinType.KIND).isInteger(); + public boolean getIsIntegerImpl() { + return this.getNodeImpl().get(BuiltinType.KIND).isInteger(); } @Override - public Boolean getIsFloatImpl() { - return builtinType.get(BuiltinType.KIND).isFloatingPoint(); + public boolean getIsFloatImpl() { + return this.getNodeImpl().get(BuiltinType.KIND).isFloatingPoint(); } @Override - public Boolean getIsSignedImpl() { - return builtinType.get(BuiltinType.KIND).isSignedInteger(); + public boolean getIsSignedImpl() { + return this.getNodeImpl().get(BuiltinType.KIND).isSignedInteger(); } @Override - public Boolean getIsUnsignedImpl() { - return builtinType.get(BuiltinType.KIND).isUnsignedInteger(); + public boolean getIsUnsignedImpl() { + return this.getNodeImpl().get(BuiltinType.KIND).isUnsignedInteger(); } @Override - public Boolean getIsVoidImpl() { - return builtinType.get(BuiltinType.KIND).isVoid(); + public boolean getIsVoidImpl() { + return this.getNodeImpl().get(BuiltinType.KIND).isVoid(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxElaboratedType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxElaboratedType.java index 8d2fea7783..73738f2cd1 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxElaboratedType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxElaboratedType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.ElaboratedType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; @@ -21,37 +20,30 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; import pt.up.fe.specs.util.SpecsStrings; -public class CxxElaboratedType extends AElaboratedType { - - private final ElaboratedType elaboratedType; +public class CxxElaboratedType> extends AElaboratedType { public CxxElaboratedType(ElaboratedType elaboratedType, CxxWeaver weaver) { - super(new CxxType(elaboratedType, weaver), weaver); - - this.elaboratedType = elaboratedType; + super(elaboratedType, weaver); } @Override - public ClavaNode getNode() { - return elaboratedType; + public ElaboratedType getNodeImpl() { + return (ElaboratedType) super.getNodeImpl(); } @Override public String getQualifierImpl() { - return SpecsStrings.nullIfEmpty(elaboratedType.getQualifier()); - // String qualifier = elaboratedType.get(ElaboratedType.QUALIFIER); - // - // return qualifier.isEmpty() ? null : qualifier; + return SpecsStrings.nullIfEmpty(this.getNodeImpl().getQualifier()); } @Override public String getKeywordImpl() { - return SpecsStrings.nullIfEmpty(elaboratedType.getKeyword().getCode()); + return SpecsStrings.nullIfEmpty(this.getNodeImpl().getKeyword().getCode()); } @Override - public AType getNamedTypeImpl() { - return CxxJoinpoints.create(elaboratedType.get(ElaboratedType.NAMED_TYPE), getWeaverEngine(), AType.class); + public AType getNamedTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().get(ElaboratedType.NAMED_TYPE), getWeaverEngine(), AType.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxEnumType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxEnumType.java index ddd9418d12..47568bfd9e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxEnumType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxEnumType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.extra.App; import pt.up.fe.specs.clava.ast.type.EnumType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -22,28 +21,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; import pt.up.fe.specs.util.SpecsLogs; -public class CxxEnumType extends AEnumType { - private final EnumType enumType; +public class CxxEnumType> extends AEnumType { public CxxEnumType(EnumType enumType, CxxWeaver weaver) { - super(new CxxTagType(enumType, weaver), weaver); - - this.enumType = enumType; + super(enumType, weaver); } @Override - public ClavaNode getNode() { - return enumType; + public EnumType getNodeImpl() { + return (EnumType) super.getNodeImpl(); } @Override - public AType getIntegerTypeImpl() { - if (getRoot() == null) { + public AType getIntegerTypeImpl() { + if (getRootImpl() == null) { SpecsLogs.msgInfo("Root not defined, is this a detached join point? -> " + this); return null; } - return CxxJoinpoints.create(enumType.getEnumDecl((App) getRootImpl().getNode()).getIntegerType(), getWeaverEngine(), AType.class); + return CxxJoinpoints.create(this.getNodeImpl().getEnumDecl((App) getRootImpl().getNodeImpl()).getIntegerType(), getWeaverEngine(), AType.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxFunctionType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxFunctionType.java index b2f215ca38..e7bece6fd4 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxFunctionType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxFunctionType.java @@ -20,43 +20,38 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AFunctionType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxFunctionType extends AFunctionType { - - private final FunctionType type; +public class CxxFunctionType> extends AFunctionType { public CxxFunctionType(FunctionType type, CxxWeaver weaver) { - super(new CxxType(type, weaver), weaver); - this.type = type; + super(type, weaver); } @Override - public Type getNode() { - return type; + public FunctionType getNodeImpl() { + return (FunctionType) super.getNodeImpl(); } @Override - public AType getReturnTypeImpl() { - return CxxJoinpoints.create(type.getReturnType(), getWeaverEngine(), AType.class); + public AType getReturnTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getReturnType(), getWeaverEngine(), AType.class); } @Override - public AType[] getParamTypesArrayImpl() { - - return type.getParamTypes().stream() - .map(paramType -> CxxJoinpoints.create(paramType, getWeaverEngine())) - .toArray(size -> new AType[size]); - + public AType[] getParamTypesImpl() { + return this.getNodeImpl().getParamTypes().stream() + .map(paramType -> CxxJoinpoints.create(paramType, getWeaverEngine(), AType.class)) + .toArray(AType[]::new); } @Override - public void setReturnTypeImpl(AType newType) { - Type newClavaType = (Type) newType.getNode(); - type.set(FunctionType.RETURN_TYPE, newClavaType); + public void setReturnTypeImpl(AType newType) { + Type newClavaType = (Type) newType.getNodeImpl(); + this.getNodeImpl().set(FunctionType.RETURN_TYPE, newClavaType); } @Override - public void setParamTypeImpl(int index, AType newType) { - type.setParamType(index, (Type) newType.getNode()); + public void setParamTypeImpl(int index, AType newType) { + this.getNodeImpl().setParamType(index, (Type) newType.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxIncompleteArrayType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxIncompleteArrayType.java index 23e1029d26..4fd5ede498 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxIncompleteArrayType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxIncompleteArrayType.java @@ -13,24 +13,19 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.IncompleteArrayType; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AIncompleteArrayType; -public class CxxIncompleteArrayType extends AIncompleteArrayType { - - private final IncompleteArrayType arrayType; +public class CxxIncompleteArrayType> extends AIncompleteArrayType { public CxxIncompleteArrayType(IncompleteArrayType arrayType, CxxWeaver weaver) { - super(new CxxArrayType(arrayType, weaver), weaver); - - this.arrayType = arrayType; + super(arrayType, weaver); } @Override - public ClavaNode getNode() { - return arrayType; + public IncompleteArrayType getNodeImpl() { + return (IncompleteArrayType) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxParenType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxParenType.java index 5c1c07265c..4e50c9af98 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxParenType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxParenType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.ParenType; import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,29 +20,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AParenType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxParenType extends AParenType { - - private final ParenType parenType; +public class CxxParenType> extends AParenType { public CxxParenType(ParenType parenType, CxxWeaver weaver) { - super(new CxxType(parenType, weaver), weaver); - - this.parenType = parenType; + super(parenType, weaver); } @Override - public ClavaNode getNode() { - return parenType; + public ParenType getNodeImpl() { + return (ParenType) super.getNodeImpl(); } @Override - public AType getInnerTypeImpl() { - return CxxJoinpoints.create(parenType.getInnerType(), getWeaverEngine(), AType.class); + public AType getInnerTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getInnerType(), getWeaverEngine(), AType.class); } @Override - public void setInnerTypeImpl(AType innerType) { - var newType = (Type) innerType.getNode(); - parenType.setInnerType(newType); + public void setInnerTypeImpl(AType innerType) { + var newType = (Type) innerType.getNodeImpl(); + this.getNodeImpl().setInnerType(newType); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxPointerType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxPointerType.java index e2a6baedf0..78bb606ca5 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxPointerType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxPointerType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.PointerType; import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,34 +20,30 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.APointerType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxPointerType extends APointerType { - - private final PointerType pointerType; +public class CxxPointerType> extends APointerType { public CxxPointerType(PointerType pointerType, CxxWeaver weaver) { - super(new CxxType(pointerType, weaver), weaver); - - this.pointerType = pointerType; + super(pointerType, weaver); } @Override - public ClavaNode getNode() { - return pointerType; + public PointerType getNodeImpl() { + return (PointerType) super.getNodeImpl(); } @Override - public AType getPointeeImpl() { - return CxxJoinpoints.create(pointerType.getPointeeType(), getWeaverEngine(), AType.class); + public AType getPointeeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getPointeeType(), getWeaverEngine(), AType.class); } @Override - public Integer getPointerLevelsImpl() { - return pointerType.getPointerLevels(); + public int getPointerLevelsImpl() { + return this.getNodeImpl().getPointerLevels(); } @Override - public void setPointeeImpl(AType pointeeType) { - pointerType.set(PointerType.POINTEE_TYPE, (Type) pointeeType.getNode()); + public void setPointeeImpl(AType pointeeType) { + this.getNodeImpl().set(PointerType.POINTEE_TYPE, (Type) pointeeType.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxQualType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxQualType.java index d9302ee271..94078ce1cb 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxQualType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxQualType.java @@ -13,35 +13,30 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.QualType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AQualType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxQualType extends AQualType { - - private final QualType qualType; +public class CxxQualType> extends AQualType { public CxxQualType(QualType qualType, CxxWeaver weaver) { - super(new CxxType(qualType, weaver), weaver); - - this.qualType = qualType; + super(qualType, weaver); } @Override - public ClavaNode getNode() { - return qualType; + public QualType getNodeImpl() { + return (QualType) super.getNodeImpl(); } @Override - public String[] getQualifiersArrayImpl() { - return qualType.getQualifierStrings().toArray(new String[0]); + public String[] getQualifiersImpl() { + return this.getNodeImpl().getQualifierStrings().toArray(new String[0]); } @Override - public AType getUnqualifiedTypeImpl() { - return CxxJoinpoints.create(qualType.getUnqualifiedType(), getWeaverEngine(), AType.class); + public AType getUnqualifiedTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getUnqualifiedType(), getWeaverEngine(), AType.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTagType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTagType.java index dcb21a6bd9..9f687653b9 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTagType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTagType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.TagDecl; import pt.up.fe.specs.clava.ast.type.TagType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,28 +20,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ADecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATagType; -public class CxxTagType extends ATagType { - private final TagType tagType; +public class CxxTagType> extends ATagType { public CxxTagType(TagType tagType, CxxWeaver weaver) { - super(new CxxType(tagType, weaver), weaver); - - this.tagType = tagType; + super(tagType, weaver); } @Override - public ClavaNode getNode() { - return tagType; + public TagType getNodeImpl() { + return (TagType) super.getNodeImpl(); } @Override public String getNameImpl() { - return tagType.get(TagType.DECL).get(TagDecl.DECL_NAME); + return this.getNodeImpl().get(TagType.DECL).get(TagDecl.DECL_NAME); } @Override - public ADecl getDeclImpl() { - return CxxJoinpoints.create(tagType.getDecl(), getWeaverEngine(), ADecl.class); + public ADecl getDeclImpl() { + return CxxJoinpoints.create(this.getNodeImpl().getDecl(), getWeaverEngine(), ADecl.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTemplateSpecializationType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTemplateSpecializationType.java index 0e14b963ff..04e0c2055a 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTemplateSpecializationType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTemplateSpecializationType.java @@ -16,7 +16,6 @@ import java.util.List; import pt.up.fe.specs.clava.ClavaLog; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.type.TemplateSpecializationType; import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -24,42 +23,38 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATemplateSpecializationType; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxTemplateSpecializationType extends ATemplateSpecializationType { - private final TemplateSpecializationType templateSpecializationType; +public class CxxTemplateSpecializationType> extends ATemplateSpecializationType { public CxxTemplateSpecializationType(TemplateSpecializationType templateSpecializationType, CxxWeaver weaver) { - - super(new CxxType(templateSpecializationType, weaver), weaver); - - this.templateSpecializationType = templateSpecializationType; + super(templateSpecializationType, weaver); } @Override - public ClavaNode getNode() { - return templateSpecializationType; + public TemplateSpecializationType getNodeImpl() { + return (TemplateSpecializationType) super.getNodeImpl(); } @Override public String getTemplateNameImpl() { - return templateSpecializationType.getTemplateName(); + return this.getNodeImpl().getTemplateName(); } @Override - public Integer getNumArgsImpl() { - return templateSpecializationType.getTemplateArguments().size(); + public int getNumArgsImpl() { + return this.getNodeImpl().getTemplateArguments().size(); } @Override - public String[] getArgsArrayImpl() { - return templateSpecializationType.getTemplateArgumentStrings(null).toArray(new String[0]); + public String[] getArgsImpl() { + return this.getNodeImpl().getTemplateArgumentStrings(null).toArray(new String[0]); } @Override - public AType getFirstArgTypeImpl() { + public AType getFirstArgTypeImpl() { ClavaLog.deprecated( "$templateSpecializationType.firstArgType is deprecated, please use $type.templateArgTypes"); - List templateArgTypes = templateSpecializationType.getTemplateArgumentTypes(); + List templateArgTypes = this.getNodeImpl().getTemplateArgumentTypes(); if (templateArgTypes.isEmpty()) { return null; } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxType.java index 33c0076d4c..5e9543992f 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -35,110 +34,93 @@ import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AType; -public class CxxType extends AType { - - private final Type type; +public class CxxType> extends AType { public CxxType(Type type, CxxWeaver weaver) { - super(weaver); - this.type = type; + super(type, weaver); } @Override - public Type getNode() { - return type; + public Type getNodeImpl() { + return (Type) super.getNodeImpl(); } @Override - public Boolean getIsArrayImpl() { - return type.isArray(); - // return type instanceof ArrayType; + public boolean getIsArrayImpl() { + return this.getNodeImpl().isArray(); } @Override - public Integer getArraySizeImpl() { - if (!(type instanceof ConstantArrayType)) { + public int getArraySizeImpl() { + if (!(this.getNodeImpl() instanceof ConstantArrayType)) { return -1; } - return ((ConstantArrayType) type).getArraySize(); + return ((ConstantArrayType) this.getNodeImpl()).getArraySize(); } @Override - public int[] getArrayDimsArrayImpl() { - if (!(type instanceof ArrayType)) { + public int[] getArrayDimsImpl() { + if (!(this.getNodeImpl() instanceof ArrayType)) { return new int[0]; } - return ((ArrayType) type).getArrayDims().stream().mapToInt(Integer::intValue).toArray(); - } - /* - @Override - public AJoinPoint getElementTypeImpl() { - if (type instanceof ArrayType) { - return CxxJoinpoints.create(((ArrayType) type).getElementType(), this); - } - - return this; + return ((ArrayType) this.getNodeImpl()).getArrayDims().stream().mapToInt(Integer::intValue).toArray(); } - */ @Override - public Boolean getHasTemplateArgsImpl() { - return type.hasTemplateArgs(); + public boolean getHasTemplateArgsImpl() { + return this.getNodeImpl().hasTemplateArgs(); } @Override - public String[] getTemplateArgsStringsArrayImpl() { - return type.getTemplateArgumentStrings(null).toArray(new String[0]); + public String[] getTemplateArgsStringsImpl() { + return this.getNodeImpl().getTemplateArgumentStrings(null).toArray(new String[0]); } @Override - public Boolean getHasSugarImpl() { - // return type.getTypeData().hasSugar(); - return type.hasSugar(); - + public boolean getHasSugarImpl() { + return this.getNodeImpl().hasSugar(); } @Override - public AType getDesugarImpl() { - return CxxJoinpoints.create(type.desugar(), getWeaverEngine(), AType.class); + public AType getDesugarImpl() { + return CxxJoinpoints.create(this.getNodeImpl().desugar(), getWeaverEngine(), AType.class); } @Override - public AType getDesugarAllImpl() { - return CxxJoinpoints.create(type.desugarAll(), getWeaverEngine(), AType.class); + public AType getDesugarAllImpl() { + return CxxJoinpoints.create(this.getNodeImpl().desugarAll(), getWeaverEngine(), AType.class); } @Override - public void setDesugarImpl(AType desugaredType) { - type.setDesugar((Type) desugaredType.getNode()); + public void setDesugarImpl(AType desugaredType) { + this.getNodeImpl().setDesugar((Type) desugaredType.getNodeImpl()); } @Override - public Boolean getIsBuiltinImpl() { - return type instanceof BuiltinType; + public boolean getIsBuiltinImpl() { + return this.getNodeImpl() instanceof BuiltinType; } @Override - public Boolean getConstantImpl() { - return type.isConst(); + public boolean getConstantImpl() { + return this.getNodeImpl().isConst(); } @Override public String getKindImpl() { - return type.getNodeName(); + return this.getNodeImpl().getNodeName(); } @Override - public Boolean getIsPointerImpl() { - return type.isPointer(); - // return type instanceof PointerType; + public boolean getIsPointerImpl() { + return this.getNodeImpl().isPointer(); } @Override - public AType getUnwrapImpl() { - Type unwrappedType = Types.getSingleElement(type); + public AType getUnwrapImpl() { + Type unwrappedType = Types.getSingleElement(this.getNodeImpl()); if (unwrappedType == null) { return null; @@ -148,51 +130,51 @@ public AType getUnwrapImpl() { } @Override - public Boolean getIsTopLevelImpl() { + public boolean getIsTopLevelImpl() { // Type is top-level if it has not parent - return !type.hasParent(); + return !this.getNodeImpl().hasParent(); } @Override - public AType[] getTemplateArgsTypesArrayImpl() { - return type.getTemplateArgumentTypes().stream() + public AType[] getTemplateArgsTypesImpl() { + return this.getNodeImpl().getTemplateArgumentTypes().stream() .map(argType -> CxxJoinpoints.create(argType, getWeaverEngine(), AType.class)) - .toArray(size -> new AType[size]); + .toArray(AType[]::new); } @Override - public void setTemplateArgsTypesImpl(AType[] templateArgTypes) { + public void setTemplateArgsTypesImpl(AType[] templateArgTypes) { List argTypes = Arrays.stream( templateArgTypes) - .map(aType -> (Type) aType.getNode()) + .map(aType -> (Type) aType.getNodeImpl()) .collect(Collectors.toList()); - type.setTemplateArgumentTypes(argTypes); + this.getNodeImpl().setTemplateArgumentTypes(argTypes); } @Override - public void setTemplateArgTypeImpl(int index, AType templateArgType) { - type.setTemplateArgumentType(index, (Type) templateArgType.getNode()); + public void setTemplateArgTypeImpl(int index, AType templateArgType) { + this.getNodeImpl().setTemplateArgumentType(index, (Type) templateArgType.getNodeImpl()); } @Override - public AType getNormalizeImpl() { - return CxxJoinpoints.create(type.normalize(), getWeaverEngine(), AType.class); + public AType getNormalizeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().normalize(), getWeaverEngine(), AType.class); } @Override - public Map getTypeFieldsImpl() { - Map typeFields = new HashMap<>(); + public Map> getTypeFieldsImpl() { + Map> typeFields = new HashMap<>(); - List> keys = type.getAllKeysWithNodes(); + List> keys = this.getNodeImpl().getAllKeysWithNodes(); for (DataKey key : keys) { - if (!type.hasValue(key)) { + if (!this.getNodeImpl().hasValue(key)) { continue; } - List values = type.getClavaNode(key); + List values = this.getNodeImpl().getClavaNode(key); // Skip fields that contain more than one node if (values.size() != 1) { @@ -215,54 +197,43 @@ public boolean setTypeFieldByValueRecursiveImpl(Object currentValue, Object newV return setTypeFieldByValueRecursiveImpl(this, currentValue, newValue, new HashSet<>()); } - private static boolean setTypeFieldByValueRecursiveImpl(AType type, Object currentValue, Object newValue, + private static boolean setTypeFieldByValueRecursiveImpl(AType type, Object currentValue, Object newValue, Set checkedNodes) { // If already visited this node, return false - if (checkedNodes.contains(type.getNode())) { + if (checkedNodes.contains(type.getNodeImpl())) { return false; } // Otherwise, add current node else { - checkedNodes.add((Type) type.getNode()); + checkedNodes.add((Type) type.getNodeImpl()); } // Get keys with type fields - @SuppressWarnings("unchecked") - Map typeFields = (Map) type.getTypeFieldsImpl(); - - List visitedTypes = new ArrayList<>(); + Map> typeFields = type.getTypeFieldsImpl(); // Iterate over each type field - for (Entry entry : typeFields.entrySet()) { + for (Entry> entry : typeFields.entrySet()) { // Found value to change, change it and return - if (entry.getValue().equals(currentValue)) { - // System.out.println("SETTING " + newValue.getClass() + " to " + entry); - // System.out.println( - // "1.Replacing " + entry.getKey() + " with value " + entry.getValue().getNode().toTree() - // + " with " - // + ((AType) newValue).getNode().toTree()); - type.setValueImpl(entry.getKey(), newValue); - return true; + if (currentValue instanceof CxxType cxxType){ + if (((AType)entry.getValue()).getEqualsImpl(cxxType)) { + type.setValueImpl(entry.getKey(), newValue); + return true; + } } - - visitedTypes.add(entry.getValue()); } // Did not find a key in the current node, call the function recursively on a copy of the visited fields // If a field is changed, update it - for (Entry entry : typeFields.entrySet()) { - AType fieldTypeCopy = (AType) entry.getValue().copy(); + for (Entry> entry : typeFields.entrySet()) { + AType fieldTypeCopy = (AType) entry.getValue().copyImpl(); boolean changedField = setTypeFieldByValueRecursiveImpl(fieldTypeCopy, currentValue, newValue, checkedNodes); // Update field if (changedField) { - // System.out.println( - // "2.Replacing " + entry.getKey() + " with value " + entry.getValue().getNode().toTree() - // + " with " + fieldTypeCopy.getNode().toTree()); - type.setValue(entry.getKey(), fieldTypeCopy); + type.setValueImpl(entry.getKey(), fieldTypeCopy); return true; } } @@ -271,22 +242,22 @@ private static boolean setTypeFieldByValueRecursiveImpl(AType type, Object curre @Override public String getFieldTreeImpl() { - return type.toFieldTree(); + return this.getNodeImpl().toFieldTree(); } @Override - public AType setUnderlyingTypeImpl(AType oldValue, AType newValue) { - return CxxJoinpoints.create(type.setUnderlyingType((Type) oldValue.getNode(), (Type) newValue.getNode()), + public AType setUnderlyingTypeImpl(AType oldValue, AType newValue) { + return CxxJoinpoints.create(this.getNodeImpl().setUnderlyingType((Type) oldValue.getNodeImpl(), (Type) newValue.getNodeImpl()), getWeaverEngine(), AType.class); } @Override - public Boolean getIsAutoImpl() { - return type.isAuto(); + public boolean getIsAutoImpl() { + return this.getNodeImpl().isAuto(); } @Override - public AType asConstImpl() { - return CxxJoinpoints.create(type.asConst(), getWeaverEngine(), AType.class); + public AType asConstImpl() { + return CxxJoinpoints.create(this.getNodeImpl().asConst(), getWeaverEngine(), AType.class); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTypedefType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTypedefType.java index 8e6f07a384..879b197468 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTypedefType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxTypedefType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.decl.TypedefNameDecl; import pt.up.fe.specs.clava.ast.type.TypedefType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -22,28 +21,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATypedefNameDecl; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.ATypedefType; -public class CxxTypedefType extends ATypedefType { - - private final TypedefType typedefType; +public class CxxTypedefType> extends ATypedefType { public CxxTypedefType(TypedefType typedefType, CxxWeaver weaver) { - super(new CxxType(typedefType, weaver), weaver); - this.typedefType = typedefType; + super(typedefType, weaver); } @Override - public ATypedefNameDecl getDeclImpl() { - return CxxJoinpoints.create(typedefType.get(TypedefType.DECL), getWeaverEngine(), ATypedefNameDecl.class); + public TypedefType getNodeImpl() { + return (TypedefType) super.getNodeImpl(); } @Override - public ClavaNode getNode() { - return typedefType; + public ATypedefNameDecl getDeclImpl() { + return CxxJoinpoints.create(this.getNodeImpl().get(TypedefType.DECL), getWeaverEngine(), ATypedefNameDecl.class); } @Override - public AType getUnderlyingTypeImpl() { - return CxxJoinpoints.create(typedefType.get(TypedefType.DECL).get(TypedefNameDecl.UNDERLYING_TYPE), + public AType getUnderlyingTypeImpl() { + return CxxJoinpoints.create(this.getNodeImpl().get(TypedefType.DECL).get(TypedefNameDecl.UNDERLYING_TYPE), getWeaverEngine(), AType.class); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxUndefinedType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxUndefinedType.java index 57af710509..c78515c36d 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxUndefinedType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxUndefinedType.java @@ -14,23 +14,18 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; import pt.up.fe.specs.clava.ast.type.NullType; -import pt.up.fe.specs.clava.ast.type.Type; import pt.up.fe.specs.clava.weaver.CxxWeaver; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AUndefinedType; -public class CxxUndefinedType extends AUndefinedType { - - private final NullType nullType; +public class CxxUndefinedType> extends AUndefinedType { public CxxUndefinedType(NullType nullType, CxxWeaver weaver) { - super(new CxxType(nullType, weaver), weaver); - - this.nullType = nullType; + super(nullType, weaver); } @Override - public Type getNode() { - return nullType; + public NullType getNodeImpl() { + return (NullType) super.getNodeImpl(); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxVariableArrayType.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxVariableArrayType.java index 379f321971..b2230051e1 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxVariableArrayType.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/joinpoints/types/CxxVariableArrayType.java @@ -13,7 +13,6 @@ package pt.up.fe.specs.clava.weaver.joinpoints.types; -import pt.up.fe.specs.clava.ClavaNode; import pt.up.fe.specs.clava.ast.expr.Expr; import pt.up.fe.specs.clava.ast.type.VariableArrayType; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; @@ -21,29 +20,25 @@ import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AExpression; import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AVariableArrayType; -public class CxxVariableArrayType extends AVariableArrayType { - - private final VariableArrayType arrayType; +public class CxxVariableArrayType> extends AVariableArrayType { public CxxVariableArrayType(VariableArrayType arrayType, CxxWeaver weaver) { - super(new CxxArrayType(arrayType, weaver), weaver); - - this.arrayType = arrayType; + super(arrayType, weaver); } @Override - public ClavaNode getNode() { - return arrayType; + public VariableArrayType getNodeImpl() { + return (VariableArrayType) super.getNodeImpl(); } @Override - public AExpression getSizeExprImpl() { - return CxxJoinpoints.create(arrayType.get(VariableArrayType.SIZE_EXPR), getWeaverEngine(), AExpression.class); + public AExpression getSizeExprImpl() { + return CxxJoinpoints.create(this.getNodeImpl().get(VariableArrayType.SIZE_EXPR), getWeaverEngine(), AExpression.class); } @Override - public void setSizeExprImpl(AExpression sizeExpr) { - arrayType.set(VariableArrayType.SIZE_EXPR, (Expr) sizeExpr.getNode()); + public void setSizeExprImpl(AExpression sizeExpr) { + this.getNodeImpl().set(VariableArrayType.SIZE_EXPR, (Expr) sizeExpr.getNodeImpl()); } } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaDirective.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaDirective.java index 3750c25e39..a92fae203d 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaDirective.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaDirective.java @@ -13,10 +13,10 @@ package pt.up.fe.specs.clava.weaver.pragmas; -import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinPoint; +import pt.up.fe.specs.clava.weaver.abstracts.joinpoints.AJoinpoint; public interface ClavaDirective { - public void apply(AJoinPoint jp); + public void apply(AJoinpoint jp); } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaPragmas.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaPragmas.java index 87ce085984..e90d7dd30e 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaPragmas.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/pragmas/ClavaPragmas.java @@ -23,7 +23,6 @@ import pt.up.fe.specs.clava.ast.pragma.Pragma; import pt.up.fe.specs.clava.weaver.CxxJoinpoints; import pt.up.fe.specs.clava.weaver.CxxWeaver; -import pt.up.fe.specs.clava.weaver.abstracts.ACxxWeaverJoinPoint; import pt.up.fe.specs.util.stringparser.StringParser; import pt.up.fe.specs.util.stringparser.StringParsers; @@ -51,7 +50,7 @@ private static void processClavaPragma(Pragma clavaPragma, CxxWeaver weaver) { return; } - ACxxWeaverJoinPoint jp = CxxJoinpoints.create(targetNode.get(), weaver); + var jp = CxxJoinpoints.create(targetNode.get(), weaver); clavaDirective.ifPresent(directive -> directive.apply(jp)); return; } diff --git a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/utils/ClavaAstMethods.java b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/utils/ClavaAstMethods.java index e178ca99b1..ec355eb567 100644 --- a/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/utils/ClavaAstMethods.java +++ b/ClavaWeaver/src/pt/up/fe/specs/clava/weaver/utils/ClavaAstMethods.java @@ -17,7 +17,7 @@ import java.util.function.Function; import org.lara.interpreter.weaver.ast.TreeNodeAstMethods; -import org.lara.interpreter.weaver.interf.JoinPoint; +import org.lara.interpreter.weaver.interf.JoinPoint2; import org.lara.interpreter.weaver.interf.WeaverEngine; import pt.up.fe.specs.clava.ClavaNode; @@ -44,7 +44,7 @@ public class ClavaAstMethods extends TreeNodeAstMethods { } public ClavaAstMethods(WeaverEngine engine, Class nodeClass, - Function toJoinPointFunction, Function toJoinPointNameFunction, + Function> toJoinPointFunction, Function toJoinPointNameFunction, Function> scopeChildrenGetter) { super(engine, nodeClass, toJoinPointFunction, toJoinPointNameFunction, scopeChildrenGetter); diff --git a/README.md b/README.md index c7ea3845f6..31d2ce60d5 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ There are three distributions of Clava: ### NPM distribution (recommended) -Clava is currently distributed as an [NPM package](https://www.npmjs.com/package/@specs-feup/clava). It requires Node.js 20 or 22, and Java 17 or higher. Different OSses have different ways of installing these dependencies, but on Ubuntu you can run this: +Clava is currently distributed as an [NPM package](https://www.npmjs.com/package/@specs-feup/clava). It requires Node.js 24 or higher, and Java 17 or higher. Different OSses have different ways of installing these dependencies, but on Ubuntu you can run this: ```bash apt-get update && apt-get install -y curl openjdk-17-jdk -curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt-get install -y nodejs +curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && apt-get install -y nodejs ``` Now, you have two options: @@ -80,16 +80,16 @@ This is a non-exhaustive list of Clava documentation, usage examples and feature * [CMake integration](https://github.com/specs-feup/clava/tree/master/CMake) - Allows Clava to be used in CMake-centered compilation flows * Code transformations: * [Automatic insertion of OpenMP pragmas](https://github.com/specs-feup/clava/blob/master/ClavaLaraApi/src-lara-clava/clava/clava/autopar/Parallelize.lara) - * [Function inlining](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/opt/Inlining.ts) - * [Normalizing code](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/opt/NormalizeToSubset.ts) to a subset of the language, including: - * [Decomposition of complex statements into several, simpler statements](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/code/StatementDecomposer.ts) - * [Converting static local variables to static global variables](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/pass/LocalStaticToGlobal.ts) - * [Conversion of switch statements to ifs](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/pass/TransformSwitchToIf.ts) - * Loop conversion ([for to while](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/code/ForToWhileStmt.ts), [do to while](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/code/DoToWhileStmt.ts)) - * [Ensure there is a single return in a function](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/pass/SingleReturnFunction.ts) - * [Remove variable shadowing](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/code/RemoveShadowing.ts) - * [Simplify ternary operator](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/code/SimplifyTernaryOp.ts) - * [Simplify compound assignments](https://github.com/specs-feup/clava/blob/master/Clava-JS/src-api/clava/code/SimplifyAssignment.ts) + * [Function inlining](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/opt/Inlining.ts) + * [Normalizing code](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/opt/NormalizeToSubset.ts) to a subset of the language, including: + * [Decomposition of complex statements into several, simpler statements](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/code/StatementDecomposer.ts) + * [Converting static local variables to static global variables](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/pass/LocalStaticToGlobal.ts) + * [Conversion of switch statements to ifs](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/pass/TransformSwitchToIf.ts) + * Loop conversion ([for to while](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/code/ForToWhileStmt.ts), [do to while](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/code/DoToWhileStmt.ts)) + * [Ensure there is a single return in a function](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/pass/SingleReturnFunction.ts) + * [Remove variable shadowing](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/code/RemoveShadowing.ts) + * [Simplify ternary operator](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/code/SimplifyTernaryOp.ts) + * [Simplify compound assignments](https://github.com/specs-feup/clava/blob/master/Clava-JS/api/clava/code/SimplifyAssignment.ts) * Clava [NPM libraries](https://www.npmjs.com/org/specs-feup) (not supported by the JAR file legacy distribution): Library | Description | Installation diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..e1da408aa6 --- /dev/null +++ b/build.gradle @@ -0,0 +1,155 @@ +import groovy.json.JsonOutput + +plugins { + id 'base' + id 'jacoco' +} + +jacoco { + toolVersion = '0.8.13' +} + +repositories { + mavenCentral() +} + +configurations { + jacocoRuntimeAgent +} + +dependencies { + jacocoRuntimeAgent("org.jacoco:org.jacoco.agent:${jacoco.toolVersion}") { + artifact { + classifier = 'runtime' + extension = 'jar' + } + transitive = false + } +} + +def workspaceRoot = layout.projectDirectory.dir('..') +def clavaJsJacocoExec = layout.buildDirectory.file('jacoco/clava-js.exec') + +def clavaJavaBuilds = [ + 'AntarexClavaApi', + 'ClangAstParser', + 'ClavaAst', + 'ClavaLaraApi', + 'ClavaOptionsManager', + 'ClavaWeaver' +] + +def clavaCoverageProjects = [ + [name: 'AntarexClavaApi', sourceDirs: ['src-java']], + [name: 'ClangAstParser', sourceDirs: ['src']], + [name: 'ClavaAst', sourceDirs: ['src']], + [name: 'ClavaLaraApi', sourceDirs: ['src-java']], + [name: 'ClavaOptionsManager', sourceDirs: ['src']], + [name: 'ClavaWeaver', sourceDirs: ['src', 'src-spec']] +] + +tasks.register('clavaJavaAssemble') { + group = 'build' + description = 'Assembles all Clava Java projects through the aggregate build.' + dependsOn clavaJavaBuilds.collect { gradle.includedBuild(it).task(':assemble') } +} + +tasks.register('clavaJavaTest') { + group = 'verification' + description = 'Runs the Java test tasks for all Clava Java projects.' + dependsOn clavaJavaBuilds.collect { gradle.includedBuild(it).task(':test') } + finalizedBy 'clavaMergedJacocoReport' +} + +tasks.register('installClavaWeaver') { + group = 'distribution' + description = 'Installs ClavaWeaver and synchronizes the distribution used by Clava-JS.' + dependsOn gradle.includedBuild('ClavaWeaver').task(':syncClavaJsJavaBinaries') +} + +tasks.register('npmInstall', Exec) { + group = 'build setup' + description = 'Installs npm workspace dependencies when node_modules is missing.' + workingDir = workspaceRoot.asFile + commandLine 'npm', 'install' + onlyIf { + !workspaceRoot.dir('node_modules').asFile.isDirectory() + } +} + +tasks.register('laraJsBuild', Exec) { + group = 'build' + description = 'Builds Lara-JS through the npm workspace.' + dependsOn 'npmInstall' + workingDir = workspaceRoot.asFile + commandLine 'npm', 'run', 'build', '-w', 'lara-framework/Lara-JS' +} + +tasks.register('clavaJsBuild', Exec) { + group = 'build' + description = 'Builds Clava-JS after synchronizing its Java distribution.' + dependsOn 'installClavaWeaver', 'laraJsBuild' + workingDir = workspaceRoot.asFile + commandLine 'npm', 'run', 'build', '-w', 'clava/Clava-JS' +} + +tasks.register('clavaJsTest', Exec) { + group = 'verification' + description = 'Runs Clava-JS tests with JaCoCo attached to the embedded JVM.' + dependsOn 'clavaJsBuild' + finalizedBy 'clavaMergedJacocoReport' + workingDir = workspaceRoot.asFile + commandLine 'npm', 'run', 'test', '-w', 'clava/Clava-JS' + + doFirst { + def execFile = clavaJsJacocoExec.get().asFile + execFile.parentFile.mkdirs() + if (execFile.isFile()) { + execFile.delete() + } + + def agentFile = configurations.jacocoRuntimeAgent.singleFile + def includes = 'pt.up.fe.specs.*:org.lara.*:org.suikasoft.*:larai.*' + def agentOption = "-javaagent:${agentFile.absolutePath}=destfile=${execFile.absolutePath},append=false,dumponexit=true,jmx=true,includes=${includes}" + environment 'CLAVA_JS_JAVA_OPTIONS', JsonOutput.toJson([agentOption]) + } +} + +tasks.register('clavaMergedJacocoReport', JacocoReport) { + group = 'verification' + description = 'Generates a merged Java coverage report from Gradle tests and Clava-JS tests.' + + executionData.from( + fileTree(layout.projectDirectory.asFile) { + include '*/build/jacoco/*.exec' + include '*/build/jacoco/**/*.exec' + }, + clavaJsJacocoExec + ) + + sourceDirectories.from(clavaCoverageProjects.collectMany { projectInfo -> + projectInfo.sourceDirs.collect { layout.projectDirectory.dir("${projectInfo.name}/${it}") } + }) + + classDirectories.from(clavaCoverageProjects.collect { projectInfo -> + layout.projectDirectory.dir("${projectInfo.name}/build/classes/java") + }) + + reports { + xml.required = true + html.required = true + csv.required = false + } + + onlyIf { + executionData.files.any { it.isFile() } + } +} + +tasks.named('assemble') { + dependsOn 'clavaJavaAssemble', 'clavaJsBuild' +} + +tasks.named('check') { + dependsOn 'clavaJavaTest', 'clavaJsTest' +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000000..10e329e795 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,8 @@ +rootProject.name = 'clava' + +includeBuild('AntarexClavaApi') +includeBuild('ClangAstParser') +includeBuild('ClavaAst') +includeBuild('ClavaLaraApi') +includeBuild('ClavaOptionsManager') +includeBuild('ClavaWeaver')