jaclang 0.7.11__py3-none-any.whl → 0.7.14__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.

Potentially problematic release.


This version of jaclang might be problematic. Click here for more details.

Files changed (31) hide show
  1. jaclang/cli/cli.py +10 -2
  2. jaclang/compiler/absyntree.py +19 -6
  3. jaclang/compiler/parser.py +6 -1
  4. jaclang/compiler/passes/main/import_pass.py +1 -0
  5. jaclang/compiler/passes/main/pyast_gen_pass.py +239 -40
  6. jaclang/compiler/passes/main/pyast_load_pass.py +4 -1
  7. jaclang/compiler/passes/main/tests/test_import_pass.py +5 -1
  8. jaclang/compiler/passes/main/type_check_pass.py +0 -17
  9. jaclang/compiler/passes/tool/fuse_comments_pass.py +14 -2
  10. jaclang/compiler/passes/tool/jac_formatter_pass.py +22 -10
  11. jaclang/compiler/tests/test_importer.py +1 -1
  12. jaclang/core/importer.py +126 -89
  13. jaclang/langserve/engine.py +173 -169
  14. jaclang/langserve/server.py +19 -7
  15. jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -2
  16. jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
  17. jaclang/langserve/tests/test_server.py +77 -64
  18. jaclang/langserve/utils.py +266 -0
  19. jaclang/plugin/default.py +4 -2
  20. jaclang/plugin/feature.py +2 -2
  21. jaclang/plugin/spec.py +2 -2
  22. jaclang/tests/fixtures/blankwithentry.jac +3 -0
  23. jaclang/tests/fixtures/deep/one_lev.jac +3 -0
  24. jaclang/tests/fixtures/needs_import.jac +1 -1
  25. jaclang/tests/test_cli.py +6 -6
  26. jaclang/tests/test_language.py +9 -0
  27. jaclang/tests/test_man_code.py +17 -0
  28. {jaclang-0.7.11.dist-info → jaclang-0.7.14.dist-info}/METADATA +1 -1
  29. {jaclang-0.7.11.dist-info → jaclang-0.7.14.dist-info}/RECORD +31 -30
  30. {jaclang-0.7.11.dist-info → jaclang-0.7.14.dist-info}/WHEEL +0 -0
  31. {jaclang-0.7.11.dist-info → jaclang-0.7.14.dist-info}/entry_points.txt +0 -0
@@ -5,23 +5,26 @@ from __future__ import annotations
5
5
  import asyncio
6
6
  import logging
7
7
  from concurrent.futures import ThreadPoolExecutor
8
- from enum import IntEnum
9
- from typing import Optional
8
+ from typing import Callable, Optional
10
9
 
11
10
 
12
11
  import jaclang.compiler.absyntree as ast
13
- from jaclang.compiler.compile import jac_ir_to_pass, jac_str_to_pass
12
+ from jaclang.compiler.compile import jac_str_to_pass
14
13
  from jaclang.compiler.parser import JacParser
15
14
  from jaclang.compiler.passes import Pass
16
- from jaclang.compiler.passes.main.schedules import type_checker_sched
15
+ from jaclang.compiler.passes.main.schedules import py_code_gen_typed
17
16
  from jaclang.compiler.passes.tool import FuseCommentsPass, JacFormatPass
18
- from jaclang.compiler.passes.transform import Alert
19
17
  from jaclang.langserve.utils import (
18
+ collect_all_symbols_in_scope,
20
19
  collect_symbols,
21
20
  create_range,
22
21
  find_deepest_symbol_node_at_pos,
22
+ gen_diagnostics,
23
23
  get_item_path,
24
24
  get_mod_path,
25
+ locate_affected_token,
26
+ parse_symbol_path,
27
+ resolve_completion_symbol_table,
25
28
  )
26
29
  from jaclang.vendor.pygls import uris
27
30
  from jaclang.vendor.pygls.server import LanguageServer
@@ -29,32 +32,17 @@ from jaclang.vendor.pygls.server import LanguageServer
29
32
  import lsprotocol.types as lspt
30
33
 
31
34
 
32
- class ALev(IntEnum):
33
- """Analysis Level successfully completed."""
34
-
35
- QUICK = 1
36
- DEEP = 2
37
- TYPE = 3
38
-
39
-
40
35
  class ModuleInfo:
41
36
  """Module IR and Stats."""
42
37
 
43
38
  def __init__(
44
39
  self,
45
40
  ir: ast.Module,
46
- errors: list[Alert],
47
- warnings: list[Alert],
48
- alev: ALev,
49
- parent: Optional[ModuleInfo] = None,
41
+ impl_parent: Optional[ModuleInfo] = None,
50
42
  ) -> None:
51
43
  """Initialize module info."""
52
44
  self.ir = ir
53
- self.errors = errors
54
- self.warnings = warnings
55
- self.alev = alev
56
- self.parent: Optional[ModuleInfo] = parent
57
- self.diagnostics = self.gen_diagnostics()
45
+ self.impl_parent: Optional[ModuleInfo] = impl_parent
58
46
  self.sem_tokens: list[int] = self.gen_sem_tokens()
59
47
 
60
48
  @property
@@ -62,57 +50,6 @@ class ModuleInfo:
62
50
  """Return uri."""
63
51
  return uris.from_fs_path(self.ir.loc.mod_path)
64
52
 
65
- def update_with(
66
- self,
67
- build: Pass,
68
- alev: ALev,
69
- refresh: bool = False,
70
- mod_override: Optional[ast.Module] = None,
71
- ) -> None:
72
- """Update module info."""
73
- target_mod = mod_override if mod_override else build.ir
74
- if not isinstance(target_mod, ast.Module):
75
- return
76
- self.ir = target_mod # if alev > ALev.QUICK else self.ir
77
- if refresh:
78
- self.errors = build.errors_had
79
- self.warnings = build.warnings_had
80
- else:
81
- self.errors += [
82
- i
83
- for i in build.errors_had
84
- if i not in self.errors
85
- if i.loc.mod_path == target_mod.loc.mod_path
86
- ]
87
- self.warnings += [
88
- i
89
- for i in build.warnings_had
90
- if i not in self.warnings
91
- if i.loc.mod_path == target_mod.loc.mod_path
92
- ]
93
- self.alev = alev
94
- self.diagnostics = self.gen_diagnostics()
95
- if self.alev == ALev.TYPE:
96
- self.sem_tokens = self.gen_sem_tokens()
97
-
98
- def gen_diagnostics(self) -> list[lspt.Diagnostic]:
99
- """Return diagnostics."""
100
- return [
101
- lspt.Diagnostic(
102
- range=create_range(error.loc),
103
- message=error.msg,
104
- severity=lspt.DiagnosticSeverity.Error,
105
- )
106
- for error in self.errors
107
- ] + [
108
- lspt.Diagnostic(
109
- range=create_range(warning.loc),
110
- message=warning.msg,
111
- severity=lspt.DiagnosticSeverity.Warning,
112
- )
113
- for warning in self.warnings
114
- ]
115
-
116
53
  def gen_sem_tokens(self) -> list[int]:
117
54
  """Return semantic tokens."""
118
55
  tokens = []
@@ -134,6 +71,76 @@ class ModuleInfo:
134
71
  prev_line, prev_col = line, col_start
135
72
  return tokens
136
73
 
74
+ def update_sem_tokens(
75
+ self, content_changes: lspt.DidChangeTextDocumentParams
76
+ ) -> list[int]:
77
+ """Update semantic tokens on change."""
78
+ for change in [
79
+ x
80
+ for x in content_changes.content_changes
81
+ if isinstance(x, lspt.TextDocumentContentChangeEvent_Type1)
82
+ ]:
83
+ change_start_line = change.range.start.line
84
+ change_start_char = change.range.start.character
85
+ change_end_line = change.range.end.line
86
+ change_end_char = change.range.end.character
87
+
88
+ line_delta = change.text.count("\n") - (change_end_line - change_start_line)
89
+ if line_delta == 0:
90
+ char_delta = len(change.text) - (change_end_char - change_start_char)
91
+ else:
92
+ last_newline_index = change.text.rfind("\n")
93
+ char_delta = (
94
+ len(change.text)
95
+ - last_newline_index
96
+ - 1
97
+ - change_end_char
98
+ + change_start_char
99
+ )
100
+
101
+ changed_token_index = locate_affected_token(
102
+ self.sem_tokens,
103
+ change_start_line,
104
+ change_start_char,
105
+ change_end_line,
106
+ change_end_char,
107
+ )
108
+ if changed_token_index:
109
+ self.sem_tokens[changed_token_index + 2] = max(
110
+ 1, self.sem_tokens[changed_token_index + 2] + char_delta
111
+ )
112
+ if (
113
+ len(self.sem_tokens) > changed_token_index + 5
114
+ and self.sem_tokens[changed_token_index + 5] == 0
115
+ ):
116
+ next_token_index = changed_token_index + 5
117
+ self.sem_tokens[next_token_index + 1] = max(
118
+ 0, self.sem_tokens[next_token_index + 1] + char_delta
119
+ )
120
+ return self.sem_tokens
121
+
122
+ current_token_index = 0
123
+ line_offset = 0
124
+ while current_token_index < len(self.sem_tokens):
125
+ token_line_number = self.sem_tokens[current_token_index] + line_offset
126
+ token_start_pos = self.sem_tokens[current_token_index + 1]
127
+
128
+ if token_line_number > change_start_line or (
129
+ token_line_number == change_start_line
130
+ and token_start_pos >= change_start_char
131
+ ):
132
+ self.sem_tokens[current_token_index] += line_delta
133
+ if token_line_number == change_start_line:
134
+ self.sem_tokens[current_token_index + 1] += char_delta
135
+ if token_line_number > change_end_line or (
136
+ token_line_number == change_end_line
137
+ and token_start_pos >= change_end_char
138
+ ):
139
+ break
140
+ line_offset += self.sem_tokens[current_token_index]
141
+ current_token_index += 5
142
+ return self.sem_tokens
143
+
137
144
 
138
145
  class JacLangServer(LanguageServer):
139
146
  """Class for managing workspace."""
@@ -143,68 +150,26 @@ class JacLangServer(LanguageServer):
143
150
  super().__init__("jac-lsp", "v0.1")
144
151
  self.modules: dict[str, ModuleInfo] = {}
145
152
  self.executor = ThreadPoolExecutor()
146
-
147
- async def push_diagnostics(self, file_path: str) -> None:
148
- """Push diagnostics for a file."""
149
- if file_path in self.modules:
150
- self.publish_diagnostics(
151
- file_path,
152
- self.modules[file_path].diagnostics,
153
- )
154
-
155
- def unwind_to_parent(self, file_path: str) -> str:
156
- """Unwind to parent."""
157
- orig_file_path = file_path
158
- if file_path in self.modules:
159
- while cur := self.modules[file_path].parent:
160
- file_path = cur.uri
161
- if file_path == orig_file_path and (
162
- discover := self.modules[file_path].ir.annexable_by
163
- ):
164
- file_path = uris.from_fs_path(discover)
165
- self.quick_check(file_path)
166
- return file_path
153
+ self.tasks: dict[str, asyncio.Task] = {}
167
154
 
168
155
  def update_modules(
169
- self, file_path: str, build: Pass, alev: ALev, refresh: bool = False
156
+ self, file_path: str, build: Pass, refresh: bool = False
170
157
  ) -> None:
171
158
  """Update modules."""
172
159
  if not isinstance(build.ir, ast.Module):
173
160
  self.log_error("Error with module build.")
174
161
  return
175
- if file_path in self.modules:
176
- self.modules[file_path].update_with(build, alev, refresh=refresh)
177
- else:
178
- self.modules[file_path] = ModuleInfo(
179
- ir=build.ir,
180
- errors=[
181
- i
182
- for i in build.errors_had
183
- if i.loc.mod_path == uris.to_fs_path(file_path)
184
- ],
185
- warnings=[
186
- i
187
- for i in build.warnings_had
188
- if i.loc.mod_path == uris.to_fs_path(file_path)
189
- ],
190
- alev=alev,
191
- )
162
+ keep_parent = (
163
+ self.modules[file_path].impl_parent if file_path in self.modules else None
164
+ )
165
+ self.modules[file_path] = ModuleInfo(ir=build.ir, impl_parent=keep_parent)
192
166
  for p in build.ir.mod_deps.keys():
193
167
  uri = uris.from_fs_path(p)
194
- if not refresh and uri in self.modules:
195
- self.modules[uri].update_with(
196
- build, alev, mod_override=build.ir.mod_deps[p], refresh=refresh
197
- )
198
- else:
168
+ if file_path != uri:
199
169
  self.modules[uri] = ModuleInfo(
200
170
  ir=build.ir.mod_deps[p],
201
- errors=[i for i in build.errors_had if i.loc.mod_path == p],
202
- warnings=[i for i in build.warnings_had if i.loc.mod_path == p],
203
- alev=alev,
171
+ impl_parent=self.modules[file_path],
204
172
  )
205
- self.modules[uri].parent = (
206
- self.modules[file_path] if file_path != uri else None
207
- )
208
173
 
209
174
  def quick_check(self, file_path: str) -> bool:
210
175
  """Rebuild a file."""
@@ -213,72 +178,107 @@ class JacLangServer(LanguageServer):
213
178
  build = jac_str_to_pass(
214
179
  jac_str=document.source, file_path=document.path, schedule=[]
215
180
  )
181
+ self.publish_diagnostics(
182
+ file_path,
183
+ gen_diagnostics(file_path, build.errors_had, build.warnings_had),
184
+ )
185
+ return len(build.errors_had) == 0
216
186
  except Exception as e:
217
187
  self.log_error(f"Error during syntax check: {e}")
218
188
  return False
219
- self.update_modules(file_path, build, ALev.QUICK, refresh=True)
220
- return len(self.modules[file_path].errors) == 0
221
189
 
222
- def deep_check(self, file_path: str) -> bool:
190
+ def deep_check(self, file_path: str, annex_view: Optional[str] = None) -> bool:
223
191
  """Rebuild a file and its dependencies."""
224
- if file_path not in self.modules:
225
- self.quick_check(file_path)
226
192
  try:
227
- file_path = self.unwind_to_parent(file_path)
228
- build = jac_ir_to_pass(ir=self.modules[file_path].ir)
229
- except Exception as e:
230
- self.log_error(f"Error during syntax check: {e}")
231
- return False
232
- self.update_modules(file_path, build, ALev.DEEP)
233
- return len(self.modules[file_path].errors) == 0
193
+ document = self.workspace.get_text_document(file_path)
194
+ if file_path in self.modules and (
195
+ parent := self.modules[file_path].impl_parent
196
+ ):
197
+ return self.deep_check(
198
+ uris.from_fs_path(parent.ir.loc.mod_path), annex_view=file_path
199
+ )
200
+ build = jac_str_to_pass(
201
+ jac_str=document.source,
202
+ file_path=document.path,
203
+ schedule=py_code_gen_typed,
204
+ )
205
+ self.update_modules(file_path, build)
206
+ if discover := self.modules[file_path].ir.annexable_by:
207
+ return self.deep_check(
208
+ uris.from_fs_path(discover), annex_view=file_path
209
+ )
234
210
 
235
- def type_check(self, file_path: str) -> bool:
236
- """Rebuild a file and its dependencies."""
237
- if file_path not in self.modules:
238
- self.deep_check(file_path)
239
- try:
240
- file_path = self.unwind_to_parent(file_path)
241
- build = jac_ir_to_pass(
242
- ir=self.modules[file_path].ir, schedule=type_checker_sched
211
+ self.publish_diagnostics(
212
+ file_path,
213
+ gen_diagnostics(
214
+ annex_view if annex_view else file_path,
215
+ build.errors_had,
216
+ build.warnings_had,
217
+ ),
243
218
  )
219
+ return len(build.errors_had) == 0
244
220
  except Exception as e:
245
- self.log_error(f"Error during type check: {e}")
221
+ self.log_error(f"Error during deep check: {e}")
246
222
  return False
247
- self.update_modules(file_path, build, ALev.TYPE)
248
- return len(self.modules[file_path].errors) == 0
249
223
 
250
- async def analyze_and_publish(self, uri: str, level: int = 2) -> None:
224
+ async def launch_quick_check(self, uri: str) -> None:
251
225
  """Analyze and publish diagnostics."""
252
- self.log_py(f"Analyzing {uri}...")
253
- success = await asyncio.get_event_loop().run_in_executor(
226
+ await asyncio.get_event_loop().run_in_executor(
254
227
  self.executor, self.quick_check, uri
255
228
  )
256
- await self.push_diagnostics(uri)
257
- if success and level > 0:
258
- success = await asyncio.get_event_loop().run_in_executor(
259
- self.executor, self.deep_check, uri
260
- )
261
- await self.push_diagnostics(uri)
262
- if level > 1:
263
- await asyncio.get_event_loop().run_in_executor(
264
- self.executor, self.type_check, uri
265
- )
266
- await self.push_diagnostics(uri)
229
+
230
+ async def launch_deep_check(self, uri: str) -> None:
231
+ """Analyze and publish diagnostics."""
232
+
233
+ async def run_in_executor(
234
+ func: Callable[[str, Optional[str]], bool],
235
+ file_path: str,
236
+ annex_view: Optional[str] = None,
237
+ ) -> None:
238
+ loop = asyncio.get_event_loop()
239
+ await loop.run_in_executor(self.executor, func, file_path, annex_view)
240
+
241
+ if uri in self.tasks and not self.tasks[uri].done():
242
+ self.log_py(f"Canceling {uri} deep check...")
243
+ self.tasks[uri].cancel()
244
+ del self.tasks[uri]
245
+ self.log_py(f"Analyzing {uri}...")
246
+ task = asyncio.create_task(run_in_executor(self.deep_check, uri))
247
+ self.tasks[uri] = task
248
+ await task
267
249
 
268
250
  def get_completion(
269
- self, file_path: str, position: lspt.Position
251
+ self, file_path: str, position: lspt.Position, completion_trigger: Optional[str]
270
252
  ) -> lspt.CompletionList:
271
253
  """Return completion for a file."""
272
- items = []
254
+ completion_items = []
273
255
  document = self.workspace.get_text_document(file_path)
274
- current_line = document.lines[position.line].strip()
275
- if current_line.endswith("hello."):
256
+ current_line = document.lines[position.line]
257
+ current_pos = position.character
258
+ current_symbol_path = parse_symbol_path(current_line, current_pos)
259
+ node_selected = find_deepest_symbol_node_at_pos(
260
+ self.modules[file_path].ir,
261
+ position.line,
262
+ position.character - 2,
263
+ )
276
264
 
277
- items = [
278
- lspt.CompletionItem(label="world"),
279
- lspt.CompletionItem(label="friend"),
280
- ]
281
- return lspt.CompletionList(is_incomplete=False, items=items)
265
+ mod_tab = (
266
+ self.modules[file_path].ir.sym_tab
267
+ if not node_selected
268
+ else node_selected.sym_tab
269
+ )
270
+ current_tab = self.modules[file_path].ir._sym_tab
271
+ current_symbol_table = mod_tab
272
+ if completion_trigger == ".":
273
+ completion_items = resolve_completion_symbol_table(
274
+ mod_tab, current_symbol_path, current_tab
275
+ )
276
+ else:
277
+ try: # noqa SIM105
278
+ completion_items = collect_all_symbols_in_scope(current_symbol_table)
279
+ except AttributeError:
280
+ pass
281
+ return lspt.CompletionList(is_incomplete=False, items=completion_items)
282
282
 
283
283
  def rename_module(self, old_path: str, new_path: str) -> None:
284
284
  """Rename module."""
@@ -325,6 +325,8 @@ class JacLangServer(LanguageServer):
325
325
  self, file_path: str, position: lspt.Position
326
326
  ) -> Optional[lspt.Hover]:
327
327
  """Return hover information for a file."""
328
+ if file_path not in self.modules:
329
+ return None
328
330
  node_selected = find_deepest_symbol_node_at_pos(
329
331
  self.modules[file_path].ir, position.line, position.character
330
332
  )
@@ -371,6 +373,8 @@ class JacLangServer(LanguageServer):
371
373
  self, file_path: str, position: lspt.Position
372
374
  ) -> Optional[lspt.Location]:
373
375
  """Return definition location for a file."""
376
+ if file_path not in self.modules:
377
+ return None
374
378
  node_selected: Optional[ast.AstSymbolNode] = find_deepest_symbol_node_at_pos(
375
379
  self.modules[file_path].ir, position.line, position.character
376
380
  )
@@ -9,7 +9,6 @@ from jaclang.compiler.constant import (
9
9
  JacSemTokenType as SemTokType,
10
10
  )
11
11
  from jaclang.langserve.engine import JacLangServer
12
- from jaclang.langserve.utils import debounce
13
12
 
14
13
  import lsprotocol.types as lspt
15
14
 
@@ -20,18 +19,19 @@ server = JacLangServer()
20
19
  @server.feature(lspt.TEXT_DOCUMENT_DID_SAVE)
21
20
  async def did_open(ls: JacLangServer, params: lspt.DidOpenTextDocumentParams) -> None:
22
21
  """Check syntax on change."""
23
- await ls.analyze_and_publish(params.text_document.uri)
22
+ await ls.launch_deep_check(params.text_document.uri)
24
23
  ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH)
25
24
 
26
25
 
27
26
  @server.feature(lspt.TEXT_DOCUMENT_DID_CHANGE)
28
- @debounce(0.3)
29
27
  async def did_change(
30
28
  ls: JacLangServer, params: lspt.DidChangeTextDocumentParams
31
29
  ) -> None:
32
30
  """Check syntax on change."""
33
- await ls.analyze_and_publish(params.text_document.uri, level=1)
34
- ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH)
31
+ await ls.launch_quick_check(file_path := params.text_document.uri)
32
+ if file_path in ls.modules:
33
+ ls.modules[file_path].update_sem_tokens(params)
34
+ ls.lsp.send_request(lspt.WORKSPACE_SEMANTIC_TOKENS_REFRESH)
35
35
 
36
36
 
37
37
  @server.feature(lspt.TEXT_DOCUMENT_FORMATTING)
@@ -86,11 +86,15 @@ def did_delete_files(ls: JacLangServer, params: lspt.DeleteFilesParams) -> None:
86
86
 
87
87
  @server.feature(
88
88
  lspt.TEXT_DOCUMENT_COMPLETION,
89
- lspt.CompletionOptions(trigger_characters=[".", ":", ""]),
89
+ lspt.CompletionOptions(trigger_characters=[".", ":", "a-zA-Z0-9"]),
90
90
  )
91
91
  def completion(ls: JacLangServer, params: lspt.CompletionParams) -> lspt.CompletionList:
92
92
  """Provide completion."""
93
- return ls.get_completion(params.text_document.uri, params.position)
93
+ return ls.get_completion(
94
+ params.text_document.uri,
95
+ params.position,
96
+ params.context.trigger_character if params.context else None,
97
+ )
94
98
 
95
99
 
96
100
  @server.feature(lspt.TEXT_DOCUMENT_HOVER, lspt.HoverOptions(work_done_progress=True))
@@ -134,6 +138,14 @@ def semantic_tokens_full(
134
138
  ls: JacLangServer, params: lspt.SemanticTokensParams
135
139
  ) -> lspt.SemanticTokens:
136
140
  """Provide semantic tokens."""
141
+ # import logging
142
+
143
+ # logging.info("\nGetting semantic tokens\n")
144
+ # # logging.info(ls.get_semantic_tokens(params.text_document.uri))
145
+ # i = 0
146
+ # while i < len(ls.get_semantic_tokens(params.text_document.uri).data):
147
+ # logging.info(ls.get_semantic_tokens(params.text_document.uri).data[i : i + 5])
148
+ # i += 5
137
149
  return ls.get_semantic_tokens(params.text_document.uri)
138
150
 
139
151
 
@@ -21,8 +21,34 @@ with entry:__main__ {
21
21
 
22
22
  glob x: int = 10;
23
23
 
24
- enum Color {
24
+ enum Colorenum {
25
25
  RED,
26
26
  GREEN,
27
27
  BLUE
28
- }
28
+ }
29
+
30
+ obj Colour1 {
31
+ has color1: Colorenum,
32
+ point1: int;
33
+
34
+ can get_color1 -> Colorenum;
35
+ }
36
+
37
+ :obj:Colour1:can:get_color1 -> Colorenum {
38
+ return self.color;
39
+ }
40
+
41
+ obj red :Colour1: {
42
+ has base_colorred: Colorenum = Color.RED,
43
+ pointred: int = 10;
44
+ obj color2 {
45
+ has color22: Color = Colorenum.BLUE,
46
+ point22: int = 20;
47
+ }
48
+ }
49
+
50
+ with entry:__main__ {
51
+ r = red(color1=Color.GREEN, point1=20);
52
+ print(r.get_color1());
53
+ print(r.color2.color22);
54
+ }
@@ -1,6 +1,6 @@
1
1
  import:py os;
2
2
  import:py from math, sqrt as square_root;
3
3
  import:py datetime as dt;
4
- import:jac from base_module_structure, add as adsd, subtract,x,Color as clr;
4
+ import:jac from base_module_structure, add_numbers as adsd, subtract,x,Colorenum as clr;
5
5
  import:jac base_module_structure as base_module_structure;
6
6
  import:py from py_import,add1 as ss, sub1 as subtract1,apple,Orange1;