simdref 0.0.9__tar.gz → 0.0.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {simdref-0.0.9/src/simdref.egg-info → simdref-0.0.10}/PKG-INFO +1 -1
- {simdref-0.0.9 → simdref-0.0.10}/pyproject.toml +1 -1
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/lsp.py +48 -13
- {simdref-0.0.9 → simdref-0.0.10/src/simdref.egg-info}/PKG-INFO +1 -1
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_lsp_stdio.py +22 -0
- {simdref-0.0.9 → simdref-0.0.10}/LICENSE +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/README.md +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/setup.cfg +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/__init__.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/__main__.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/annotate.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/arm_instructions.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/cli.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/display.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/export.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/filters.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/ingest.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/ingest_catalog.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/ingest_pdf.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/ingest_sources.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/manpages.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/models.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/pdfparse/__init__.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/pdfparse/base.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/pdfparse/intel.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/pdfparse/registry.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/pdfparse/types.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/pdfrefs.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/perf.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/perf_sources/__init__.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/perf_sources/cores.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/perf_sources/llvm_mca.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/perf_sources/llvm_scheduling.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/perf_sources/merge.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/queries.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/riscv.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/search.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/storage.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/tui.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref/ui_labels.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref.egg-info/SOURCES.txt +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref.egg-info/dependency_links.txt +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref.egg-info/entry_points.txt +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref.egg-info/requires.txt +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/src/simdref.egg-info/top_level.txt +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_annotate.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_annotate_positions.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_audit_coverage.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_auto_update_on_version_change.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_cli_bare_query.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_cli_bootstrap_progress.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_cli_help.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_cli_llm.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_coverage_live.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_coverage_parity.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_display.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_export.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_filters.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_ingest_sources.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_intel_operation_and_url.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_issue2_fixes.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_issues_23_24_25.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_lsp_web.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_models.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_pdfparse.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_perf.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_perf_sources.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_presentation.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_preset_persistence.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_riscv_docs_pages.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_search.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_search_pushdown.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_source_kind_filter.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_source_validation.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_storage_payload.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_storage_schema.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_tui.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_ui_labels_parity.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_version_matches_pyproject.py +0 -0
- {simdref-0.0.9 → simdref-0.0.10}/tests/test_x86_linking.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "simdref"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.10"
|
|
8
8
|
description = "Searchable SIMD intrinsic and instruction reference with CLI, manpages, TUI, and LSP."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -216,6 +216,43 @@ def _is_c_doc(language_id: str, uri: str) -> bool:
|
|
|
216
216
|
return language_id in ("c", "cpp") or uri.lower().endswith(C_EXTENSIONS)
|
|
217
217
|
|
|
218
218
|
|
|
219
|
+
def _semicolon_is_comment(language_id: str, uri: str) -> bool:
|
|
220
|
+
# A .s/.S extension means GAS syntax: ";" stays a statement separator there
|
|
221
|
+
# even if the client tags the buffer with an assembly languageId.
|
|
222
|
+
if _is_c_doc(language_id, uri):
|
|
223
|
+
return False
|
|
224
|
+
if uri.lower().endswith(".s"):
|
|
225
|
+
return False
|
|
226
|
+
return language_id in ("asm", "nasm", "masm") or uri.lower().endswith((".asm", ".nasm"))
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _asm_line_at(text: str, language_id: str, uri: str, offset: int) -> str | None:
|
|
230
|
+
"""Return the assembler segment that holds the text offset, or None.
|
|
231
|
+
|
|
232
|
+
C/C++ documents hold assembler in string literals in asm(...) calls, so the
|
|
233
|
+
segment comes from _asm_literals. In every other document the whole source
|
|
234
|
+
line is the segment. Hover and inlay hints must call this one function so
|
|
235
|
+
both parse the same text.
|
|
236
|
+
"""
|
|
237
|
+
if _is_c_doc(language_id, uri):
|
|
238
|
+
spaced = text.replace("\\t", " ")
|
|
239
|
+
for start, body in _asm_literals(spaced):
|
|
240
|
+
if start <= offset <= start + len(body):
|
|
241
|
+
cut = 0
|
|
242
|
+
for split in ASM_SPLIT_RE.finditer(body):
|
|
243
|
+
if cut <= offset - start < split.start():
|
|
244
|
+
return body[cut : split.start()]
|
|
245
|
+
cut = split.end()
|
|
246
|
+
return body[cut:]
|
|
247
|
+
return None
|
|
248
|
+
lines = text.split("\n")
|
|
249
|
+
for line, source_line in enumerate(lines):
|
|
250
|
+
end = offset - sum(len(item) + 1 for item in lines[:line])
|
|
251
|
+
if 0 <= end <= len(source_line):
|
|
252
|
+
return source_line
|
|
253
|
+
return None
|
|
254
|
+
|
|
255
|
+
|
|
219
256
|
def _asm_literals(text: str) -> list[tuple[int, str]]:
|
|
220
257
|
"""Return (offset, body) for each string literal inside an asm(...) call in C source."""
|
|
221
258
|
masked = C_TOKEN_RE.sub(
|
|
@@ -303,13 +340,7 @@ def _inlay_hints(conn, text: str, language_id: str, uri: str, start: int, end: i
|
|
|
303
340
|
db_path = conn.execute("PRAGMA database_list").fetchone()[2]
|
|
304
341
|
source_lines = [line.rstrip("\r") for line in text.split("\n")]
|
|
305
342
|
is_c_doc = _is_c_doc(language_id, uri)
|
|
306
|
-
|
|
307
|
-
# even if the client tags the buffer with an assembly languageId.
|
|
308
|
-
semicolon_is_comment = (
|
|
309
|
-
not is_c_doc
|
|
310
|
-
and not uri.lower().endswith(".s")
|
|
311
|
-
and (language_id in ("asm", "nasm", "masm") or uri.lower().endswith((".asm", ".nasm")))
|
|
312
|
-
)
|
|
343
|
+
semicolon_is_comment = _semicolon_is_comment(language_id, uri)
|
|
313
344
|
if is_c_doc:
|
|
314
345
|
candidates = [
|
|
315
346
|
(text.count("\n", 0, offset), segment)
|
|
@@ -411,12 +442,16 @@ def main() -> int:
|
|
|
411
442
|
operand_count = None
|
|
412
443
|
operand_text = ""
|
|
413
444
|
if word and allow_instruction:
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
445
|
+
offset = sum(len(item) + 1 for item in text.split("\n")[:line]) + character
|
|
446
|
+
language_id = session.languages.get(uri, "")
|
|
447
|
+
segment = _asm_line_at(text, language_id, uri, offset)
|
|
448
|
+
if segment:
|
|
449
|
+
operand_text = segment
|
|
450
|
+
parsed = _mnemonic_from_asm_line(
|
|
451
|
+
segment, _semicolon_is_comment(language_id, uri)
|
|
452
|
+
)
|
|
453
|
+
if parsed and parsed[0].casefold() == word.casefold():
|
|
454
|
+
operand_count = parsed[1]
|
|
420
455
|
body = (
|
|
421
456
|
_hover_markdown(
|
|
422
457
|
conn,
|
|
@@ -265,6 +265,28 @@ class LspEndToEndTests(unittest.TestCase):
|
|
|
265
265
|
self.server.open("file:///tmp/x.hxx", "", "int x;\n")
|
|
266
266
|
self.assertEqual(self.server.hints("file:///tmp/x.hxx"), []) # "int" is an x86 mnemonic
|
|
267
267
|
|
|
268
|
+
def test_cpp_hover_inside_asm_literal_matches_the_ymm_form(self):
|
|
269
|
+
text = 'asm volatile("vaddps %ymm2, %ymm1, %ymm0");\n'
|
|
270
|
+
self.server.open(CPP_URI, "cpp", text)
|
|
271
|
+
result = self.server.hover(CPP_URI, 0, 16)
|
|
272
|
+
self.assertIsNotNone(result, "hover on vaddps inside the asm literal returned null")
|
|
273
|
+
value = result["contents"]["value"]
|
|
274
|
+
self.assertIn("VADDPS (YMM, YMM, YMM)", value)
|
|
275
|
+
self.assertNotIn("VADDPS (XMM, K, XMM, M128)", value)
|
|
276
|
+
|
|
277
|
+
def test_asm_hover_and_hint_agree_on_semicolon_comment(self):
|
|
278
|
+
uri = "file:///tmp/simdref_lsp_test_hover.asm"
|
|
279
|
+
self.server.open(uri, "nasm", "adc eax, ebx ; j, k\n")
|
|
280
|
+
hint = self.server.hints(uri)[0]["label"]
|
|
281
|
+
result = self.server.hover(uri, 0, 1)
|
|
282
|
+
self.assertIsNotNone(result, "hover on adc returned null")
|
|
283
|
+
value = result["contents"]["value"]
|
|
284
|
+
# The hover must pick the same form as the hint on the same line. The
|
|
285
|
+
# 4-operand parse lands on an ARM adc page, the 2-operand parse on the
|
|
286
|
+
# x86 "Add With Carry." form the hint names.
|
|
287
|
+
self.assertIn("Add With Carry.", value)
|
|
288
|
+
self.assertEqual(hint, "Add With Carry.")
|
|
289
|
+
|
|
268
290
|
def test_asm_semicolon_comment_in_dot_asm_file(self):
|
|
269
291
|
uri = "file:///tmp/simdref_lsp_test.asm"
|
|
270
292
|
self.server.open(uri, "nasm", "vaddps ymm0, ymm1, ymm2 ; add, then, more\n")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|