dedekind 3.0.0__py3-none-any.whl

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.
Files changed (62) hide show
  1. dedekind/__init__.py +17 -0
  2. dedekind/aot_compiler.py +93 -0
  3. dedekind/ast_nodes.py +187 -0
  4. dedekind/build_runtime.py +14 -0
  5. dedekind/cli.py +11 -0
  6. dedekind/codegen.py +641 -0
  7. dedekind/compiler.py +379 -0
  8. dedekind/install_kernel.py +76 -0
  9. dedekind/latex_export.py +265 -0
  10. dedekind/lexer.py +110 -0
  11. dedekind/ml_runtime.py +14075 -0
  12. dedekind/mlir_codegen.py +99 -0
  13. dedekind/parser.py +786 -0
  14. dedekind/purity_check.py +151 -0
  15. dedekind/reproducibility.py +136 -0
  16. dedekind/runtime_modules/00_imports.py +92 -0
  17. dedekind/runtime_modules/01_classes.py +1270 -0
  18. dedekind/runtime_modules/02_tensors.py +291 -0
  19. dedekind/runtime_modules/03_solvers.py +2702 -0
  20. dedekind/runtime_modules/04_math.py +1258 -0
  21. dedekind/runtime_modules/05_uncertainty.py +1577 -0
  22. dedekind/runtime_modules/06_io.py +844 -0
  23. dedekind/runtime_modules/07_dataframes.py +594 -0
  24. dedekind/runtime_modules/08_advanced.py +1003 -0
  25. dedekind/runtime_modules/09_publishing.py +299 -0
  26. dedekind/runtime_modules/09_signals.py +927 -0
  27. dedekind/runtime_modules/10_robotics.py +93 -0
  28. dedekind/runtime_modules/12_fluid_dynamics.py +1858 -0
  29. dedekind/runtime_modules/14_structural.py +453 -0
  30. dedekind/runtime_modules/15_thermal.py +276 -0
  31. dedekind/runtime_modules/16_space.py +251 -0
  32. dedekind/runtime_modules/17_atomic.py +287 -0
  33. dedekind/server.py +73 -0
  34. dedekind/simplify.py +217 -0
  35. dedekind/stdlib/atomic.ddk +54 -0
  36. dedekind/stdlib/biology.ddk +101 -0
  37. dedekind/stdlib/chemistry.ddk +111 -0
  38. dedekind/stdlib/fluid_dynamics.ddk +288 -0
  39. dedekind/stdlib/math.ddk +120 -0
  40. dedekind/stdlib/ml.ddk +107 -0
  41. dedekind/stdlib/physics.ddk +121 -0
  42. dedekind/stdlib/quantum.ddk +52 -0
  43. dedekind/stdlib/robotics.ddk +16 -0
  44. dedekind/stdlib/signals.ddk +132 -0
  45. dedekind/stdlib/space.ddk +26 -0
  46. dedekind/stdlib/stats.ddk +113 -0
  47. dedekind/stdlib/structural.ddk +58 -0
  48. dedekind/stdlib/thermal.ddk +33 -0
  49. dedekind/symbolic_diff.py +415 -0
  50. dedekind/units_checker.py +267 -0
  51. dedekind-3.0.0.dist-info/METADATA +387 -0
  52. dedekind-3.0.0.dist-info/RECORD +62 -0
  53. dedekind-3.0.0.dist-info/WHEEL +5 -0
  54. dedekind-3.0.0.dist-info/entry_points.txt +3 -0
  55. dedekind-3.0.0.dist-info/licenses/LICENSE +201 -0
  56. dedekind-3.0.0.dist-info/licenses/NOTICE +24 -0
  57. dedekind-3.0.0.dist-info/top_level.txt +2 -0
  58. dedekind_jupyter_kernel/__init__.py +1 -0
  59. dedekind_jupyter_kernel/__main__.py +7 -0
  60. dedekind_jupyter_kernel/kernel.py +202 -0
  61. dedekind_jupyter_kernel/kernelspec/kernel.json +11 -0
  62. dedekind_jupyter_kernel/run_dedekind_kernel.py +24 -0
dedekind/__init__.py ADDED
@@ -0,0 +1,17 @@
1
+ """Dedekind -- a programming language for scientific computing.
2
+
3
+ Public entry points:
4
+ dedekind.compile_source(src, ...) - compile a .ddk source string to Python
5
+ dedekind.dedekind_exec(code, ...) - run compiled code with mapped tracebacks
6
+ dedekind.export_to_latex(src) - export formulas as LaTeX
7
+
8
+ CLI: `dedekind <file.ddk>` (see dedekind.cli).
9
+ """
10
+
11
+ __version__ = "3.0.0"
12
+
13
+ from .compiler import ( # noqa: F401 (re-export)
14
+ compile_source,
15
+ dedekind_exec,
16
+ export_to_latex,
17
+ )
@@ -0,0 +1,93 @@
1
+ import os
2
+ import subprocess
3
+ import sys
4
+ from .lexer import Lexer
5
+ from .parser import Parser
6
+ from .mlir_codegen import MLIRCodeGenerator
7
+
8
+ class AOTCompiler:
9
+ """
10
+ Dedekind Ahead-of-Time (AOT) Compiler.
11
+ Orchestrates the transition from Dedekind source to native binaries.
12
+ """
13
+ def __init__(self, source_path: str):
14
+ self.source_path = source_path
15
+ self.output_dir = os.path.dirname(source_path)
16
+ self.base_name = os.path.splitext(os.path.basename(source_path))[0]
17
+
18
+ def compile(self) -> str:
19
+ """
20
+ Runs the full AOT pipeline.
21
+ Returns the path to the generated binary.
22
+ """
23
+ print(f"Dedekind AOT: Compiling {self.source_path}...")
24
+
25
+ # 1. Lexing & Parsing
26
+ with open(self.source_path, 'r', encoding='utf-8') as f:
27
+ source = f.read()
28
+
29
+ lexer = Lexer(source)
30
+ tokens = lexer.tokenize()
31
+ parser = Parser(tokens)
32
+ ast = parser.parse()
33
+
34
+ # 2. MLIR Generation
35
+ mlir_gen = MLIRCodeGenerator()
36
+ mlir_ir = mlir_gen.generate(ast)
37
+
38
+ mlir_path = os.path.join(self.output_dir, f"{self.base_name}.mlir")
39
+ with open(mlir_path, 'w', encoding='utf-8') as f:
40
+ f.write(mlir_ir)
41
+ print(f"Dedekind AOT: MLIR generated at {mlir_path}")
42
+
43
+ # 3. Native Mock (Prototype v0.4)
44
+ # In a full implementation, we would call mlir-opt and mlir-translate here.
45
+ # For the prototype, we generate a companion C++ 'lowering' of the MLIR to show the path.
46
+ cpp_path = os.path.join(self.output_dir, f"{self.base_name}_native.cpp")
47
+ self._generate_cpp_stubs(mlir_ir, cpp_path)
48
+
49
+ binary_path = os.path.join(self.output_dir, f"{self.base_name}.exe")
50
+
51
+ # Attempt to compile if a C++ compiler exists
52
+ success = self._compile_to_binary(cpp_path, binary_path)
53
+
54
+ if success:
55
+ return binary_path
56
+ else:
57
+ print("Dedekind AOT: Native compiler not found. Project is ready for AOT lowering.")
58
+ return cpp_path # Return the C++ file for inspection if binary fails
59
+
60
+ def _generate_cpp_stubs(self, mlir_ir: str, output_path: str):
61
+ """Generates a C++ representation of the Dedekind program for native compilation."""
62
+ with open(output_path, 'w', encoding='utf-8') as f:
63
+ f.write("#include <iostream>\n")
64
+ f.write("#include <vector>\n\n")
65
+ f.write("// Dedekind Native Runtime Stubs\n")
66
+ f.write("int main() {\n")
67
+ f.write(" std::cout << \"--- Dedekind Native AOT Runtime ---\" << std::endl;\n")
68
+ f.write(" std::cout << \"Executing MLIR-lowered kernels...\" << std::endl;\n")
69
+ f.write(" // The AOT compiler links the Dedekind Dialect to LLVM here.\n")
70
+ f.write(f" std::cout << \"Compiled from: {self.source_path}\" << std::endl;\n")
71
+ f.write(" return 0;\n")
72
+ f.write("}\n")
73
+
74
+ def _compile_to_binary(self, cpp_path: str, output_path: str) -> bool:
75
+ """Attempts to compile the generated C++/LLVM code using system tools."""
76
+ compilers = [
77
+ ['cl', '/EHsc', cpp_path, f'/Fe:{output_path}'],
78
+ ['clang++', cpp_path, '-o', output_path],
79
+ ['g++', cpp_path, '-o', output_path],
80
+ ]
81
+ for cmd in compilers:
82
+ try:
83
+ subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
84
+ print(f"Dedekind AOT: Static binary created via {cmd[0]}")
85
+ return True
86
+ except (FileNotFoundError, subprocess.CalledProcessError):
87
+ continue
88
+ return False
89
+
90
+ if __name__ == "__main__":
91
+ if len(sys.argv) > 1:
92
+ compiler = AOTCompiler(sys.argv[1])
93
+ compiler.compile()
dedekind/ast_nodes.py ADDED
@@ -0,0 +1,187 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import List, Optional, Union, Any
3
+
4
+
5
+ class CompileError(Exception):
6
+ """Compiler error with line and optional context."""
7
+ def __init__(self, message: str, line: Optional[int] = None, filepath: Optional[str] = None):
8
+ self.message = message
9
+ self.line = line
10
+ self.filepath = filepath
11
+ super().__init__(self._format())
12
+
13
+ def _format(self) -> str:
14
+ parts = []
15
+ if self.filepath:
16
+ parts.append(self.filepath)
17
+ if self.line is not None:
18
+ parts.append(f"Line {self.line}")
19
+ parts.append(self.message)
20
+ return ": ".join(str(p) for p in parts)
21
+
22
+
23
+ @dataclass
24
+ class Node:
25
+ """Base for all AST nodes; line for error messages."""
26
+ line: Optional[int] = field(default=None, kw_only=True)
27
+
28
+ @dataclass
29
+ class Program(Node):
30
+ statements: List[Node]
31
+
32
+ @dataclass
33
+ class FunctionDef(Node):
34
+ name: str
35
+ args: List[str]
36
+ body: List[Node]
37
+ arg_units: Optional[List[Optional[str]]] = None # Per-arg unit annotations ([m], [kg], …); None per slot = not annotated
38
+ return_unit: Optional[str] = None # Return unit annotation
39
+ arg_shapes: Optional[List[Optional[List]]] = None # Per-arg shape annotations (Vector[2], Tensor[batch,N]); None per slot = not annotated
40
+ return_shape: Optional[List] = None # Return shape annotation
41
+ is_pub: bool = False # `pub fn` -> True; only relevant for module visibility
42
+ type_params: List[str] = field(default_factory=list) # `fn name<T, U>(...)`: polymorphic type parameters
43
+
44
+
45
+ @dataclass
46
+ class UseStmt(Node):
47
+ """Module/Import statement: `use math` loads math.ddk into the current compilation pass."""
48
+ module: str
49
+
50
+
51
+ @dataclass
52
+ class UnitDef(Node):
53
+ """User-defined unit: `unit Foot = 0.3048[m]` registers Foot as a length unit
54
+ with conversion factor 0.3048 to the base unit. base_unit must already belong to a known dimension."""
55
+ name: str
56
+ factor: float
57
+ base_unit: str
58
+
59
+
60
+ @dataclass
61
+ class PyImport(Node):
62
+ """Imports a Python module from the PyPI ecosystem: `pyimport scipy.special as ss`.
63
+ Generates an `import MODULE as ALIAS` in the generated code."""
64
+ module: str
65
+ alias: str
66
+
67
+ @dataclass
68
+ class ReturnStmt(Node):
69
+ value: Node
70
+
71
+ @dataclass
72
+ class Assignment(Node):
73
+ target: str
74
+ value: Node
75
+
76
+ @dataclass
77
+ class BinaryOp(Node):
78
+ left: Node
79
+ op: str
80
+ right: Node
81
+
82
+ @dataclass
83
+ class UnaryOp(Node):
84
+ """Unary operator, e.g., not x."""
85
+ op: str
86
+ operand: Node
87
+
88
+ @dataclass
89
+ class Call(Node):
90
+ func_name: Node # Can be an identifier or another call (chaining)
91
+ args: List[Node]
92
+ kwargs: List[Any] # List of (name, value) tuples
93
+ modifiers: List[str] # e.g., ['gpu', 'cpu']
94
+
95
+ @dataclass
96
+ class Identifier(Node):
97
+ name: str
98
+
99
+ @dataclass
100
+ class Literal(Node):
101
+ value: Any
102
+ raw: bool = False # True = Raw string (r"...") in Dedekind
103
+
104
+ @dataclass
105
+ class Quantity(Node):
106
+ """Physical quantity: number with unit, e.g., 10[m], 5[m/s]."""
107
+ value: Union[int, float]
108
+ unit: str
109
+
110
+ @dataclass
111
+ class QuaternionLiteral(Node):
112
+ value: float
113
+ component: str # 'i', 'j', or 'k'
114
+
115
+ @dataclass
116
+ class VectorLiteral(Node):
117
+ elements: List[Node]
118
+
119
+ @dataclass
120
+ class DictLiteral(Node):
121
+ """Dict literal: {"key": value, "k2": v2} — gets transpiled to a Python dict."""
122
+ keys: List[Node]
123
+ values: List[Node]
124
+
125
+ @dataclass
126
+ class Lambda(Node):
127
+ arg: str
128
+ body: Node
129
+
130
+ @dataclass
131
+ class IfStmt(Node):
132
+ condition: Node
133
+ then_branch: List[Node]
134
+ else_branch: Optional[List[Node]]
135
+
136
+ @dataclass
137
+ class WhileStmt(Node):
138
+ condition: Node
139
+ body: List[Node]
140
+
141
+ @dataclass
142
+ class ForStmt(Node):
143
+ variable: str
144
+ collection: Node
145
+ body: List[Node]
146
+
147
+ @dataclass
148
+ class MemberAccess(Node):
149
+ obj: Node
150
+ member: str
151
+
152
+ @dataclass
153
+ class IndexedVariable(Node):
154
+ name: str
155
+ indices: str # String of indices, e.g., "ij"
156
+
157
+ @dataclass
158
+ class Subscript(Node):
159
+ value: Node
160
+ index: Node
161
+
162
+
163
+ @dataclass
164
+ class Slice(Node):
165
+ """Python-style slice for subscript indices: x[start:stop:step].
166
+ Each component can be None (open bound)."""
167
+ start: Optional[Node] = None
168
+ stop: Optional[Node] = None
169
+ step: Optional[Node] = None
170
+
171
+
172
+ @dataclass
173
+ class TryCatch(Node):
174
+ """try { body } catch var { handler } — catches every exception and binds it to var."""
175
+ body: List[Node]
176
+ catch_var: str
177
+ handler: List[Node]
178
+
179
+ @dataclass
180
+ class ItemAssignment(Node):
181
+ target: Subscript
182
+ value: Node
183
+
184
+ @dataclass
185
+ class PostfixFactorial(Node):
186
+ """Postfix factorial: n!"""
187
+ operand: Node
@@ -0,0 +1,14 @@
1
+ import os
2
+ import glob
3
+
4
+ src_dir = os.path.join(os.path.dirname(__file__), "runtime_modules")
5
+ out_file = os.path.join(os.path.dirname(__file__), "ml_runtime.py")
6
+
7
+ modules = sorted(glob.glob(os.path.join(src_dir, "*.py")))
8
+
9
+ with open(out_file, "w", encoding="utf-8") as out:
10
+ for mod in modules:
11
+ with open(mod, "r", encoding="utf-8") as f:
12
+ out.write(f.read())
13
+
14
+ print(f"Successfully generated ml_runtime.py from {len(modules)} modules.")
dedekind/cli.py ADDED
@@ -0,0 +1,11 @@
1
+ """CLI entry point: `dedekind <file.ddk> [--latex] [--reproducibility-report PATH] ...`.
2
+
3
+ Thin wrapper around `dedekind.compiler.main()` so that pip can install a
4
+ shell command. The heavy-lifting argparse-equivalent lives in compiler.py
5
+ for legacy `python -m dedekind.compiler` invocations.
6
+ """
7
+ from .compiler import main
8
+
9
+
10
+ if __name__ == "__main__":
11
+ main()