Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Интеграция CGML-py, новый формат платформ #22

Merged
merged 14 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
602 changes: 602 additions & 0 deletions compiler/CGML.py

Large diffs are not rendered by default.

56 changes: 14 additions & 42 deletions compiler/CJsonParser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
"""Legacy module that implements parsing Lapki IDE's internal JSON scheme."""

from enum import Enum
from typing import Dict, Iterable, List, Set

from compiler.types.ide_types import Bounds
Expand All @@ -13,8 +11,8 @@
StateMachine,
ParserState,
ParserNote,
ParserNoteNodeLabel,
ParserNoteNodeContent
Labels,
create_note
)
from .types.ide_types import (
IdeStateMachine,
Expand Down Expand Up @@ -46,8 +44,8 @@
StateMachine,
ParserState,
ParserNote,
ParserNoteNodeLabel,
ParserNoteNodeContent
Labels,
create_note
)
from compiler.types.ide_types import (
IdeStateMachine,
Expand All @@ -69,20 +67,6 @@ class ParserException(Exception):
...


class Labels(Enum):
"""В fullgraphmlparser для определения, \
куда вставлять код используют метки."""

H_INCLUDE = 'Code for h-file'
H = 'Declare variable in h-file'
CPP = 'Code for cpp-file'
CTOR = 'Constructor code'
USER_VAR_H = 'User variables for h-file'
USER_VAR_C = 'User variables for c-file'
USER_FUNC_H = 'User methods for h-file'
USER_FUNC_C = 'User methods for c-file'


class CJsonParser:
"""Class for parsing Lapki IDE's internal JSON scheme."""

Expand All @@ -108,9 +92,6 @@ def _initComponent(self, component_name: str, component: Component) -> str:
"""Функция, которая в зависимости от типа компонента\
возвращает код его инициализации в h-файле."""
match component.type:
case 'Timer':
return (f'\nTimer {component_name} = Timer'
f'(the_sketch,{component_name}_timeout_SIG);')
case 'QHsmSerial':
return ''
case _:
Expand Down Expand Up @@ -151,15 +132,6 @@ def _specificCheckComponentSignal(
]
) + '\n\t}'

def _getNote(self, label: Labels, content: str) -> ParserNote:
"""Создать ParserNote на основе метки вставки, и кода для вставки."""
return ParserNote(
umlNote=ParserNoteNodeLabel(
nodeLabel=ParserNoteNodeContent(
text=f'{label.value}: {content}')
)
)

def getLibraries(self, components: List[Component]) -> Set[str]:
"""Получить используемые типы компонентов."""
libraries: Set[str] = set()
Expand Down Expand Up @@ -260,9 +232,9 @@ def _createNotes(
'}']) + '\n}'
notes.extend(
[
self._getNote(Labels.H, ''.join(variables)),
self._getNote(Labels.H_INCLUDE, ''.join(includes)),
self._getNote(Labels.CPP, '\n\n'.join(
create_note(Labels.H, ''.join(variables)),
create_note(Labels.H_INCLUDE, ''.join(includes)),
create_note(Labels.CPP, '\n\n'.join(
[setup_function, loop_function, main_function]
)
),
Expand All @@ -281,9 +253,9 @@ def _createNotes(

notes.extend(
[
self._getNote(Labels.H, ''.join(variables)),
self._getNote(Labels.H_INCLUDE, ''.join(includes)),
self._getNote(Labels.CPP, '\n\n'.join(
create_note(Labels.H, ''.join(variables)),
create_note(Labels.H_INCLUDE, ''.join(includes)),
create_note(Labels.CPP, '\n\n'.join(
[setup_function, loop_function]
)
),
Expand Down Expand Up @@ -393,7 +365,7 @@ def _getTransitions(
triggers.append(ParserTrigger(name=eventname,
source=transition.source,
target=transition.target,
id=i,
id=str(i),
type='external',
guard=condition,
action=action))
Expand Down Expand Up @@ -461,7 +433,7 @@ def _getEvents(
source=state_id,
target='',
action=actions,
id=id,
id=str(id),
)
return Events(events=result,
signals=event_signals,
Expand Down Expand Up @@ -594,8 +566,8 @@ def parseStateMachine(self, data: IdeStateMachine) -> StateMachine:
states=[global_state, *list(proccesed_states.values())],
notes=notes,
start_action='',
signals=[*player_signals.keys(),
*self._addSignals(data.components, player_signals)],
signals=set([*player_signals.keys(),
*self._addSignals(data.components, player_signals)]),
start_node=startNode
)

Expand Down
57 changes: 48 additions & 9 deletions compiler/Compiler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Module implements communication with compilers."""

from typing import Dict, List, Set, TypedDict
import os
import asyncio
from asyncio.subprocess import Process
from typing import Dict, List, Set, TypedDict

from pydantic.dataclasses import dataclass
from aiopath import AsyncPath
Expand Down Expand Up @@ -40,8 +40,8 @@ class SupportedCompiler(TypedDict):
class Compiler:
"""Class for compiling, copying libraries sources."""

c_default_libraries = set(['qhsm'])

DEFAULT_LIBRARY_ID = 'default'
c_default_libraries = set(['qhsm']) # legacy
supported_compilers: Dict[str, SupportedCompiler] = {
'gcc': {
'extension': ['.c', '.cpp'],
Expand Down Expand Up @@ -90,12 +90,36 @@ async def getBuildFiles(
...
return build_files

@staticmethod
async def compile_project(
base_dir: str,
flags: List[str],
compiler: str
) -> CompilerResult:
"""Compile project in base_dir by compiler with flags."""
process: Process = await asyncio.create_subprocess_exec(
compiler,
*flags,
cwd=base_dir,
text=False,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
await process.wait()
stdout, stderr = await process.communicate()
if process.returncode is None:
raise CompilerException('Process doesnt return code.')

return CompilerResult(process.returncode,
str(stdout.decode('utf-8')),
str(stderr.decode('utf-8')))

@staticmethod
async def compile(base_dir: str,
build_files: Set[str],
flags: List[str],
compiler: SupportedCompilers) -> CompilerResult:
"""Run compiler with choosen settings."""
"""(Legacy, use compile_project) Run compiler with choosen settings."""
match compiler:
case 'g++' | 'gcc':
await AsyncPath(base_dir + 'build/').mkdir(parents=True,
Expand All @@ -105,15 +129,15 @@ async def compile(base_dir: str,
process: Process = await asyncio.create_subprocess_exec(
compiler,
*build_files,
*flags, cwd=base_dir,
*flags,
cwd=base_dir,
text=False,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
case 'arduino-cli':
process = await asyncio.create_subprocess_exec(
compiler,
'compile',
'--export-binaries',
*flags,
*build_files,
Expand All @@ -131,16 +155,31 @@ async def compile(base_dir: str,
str(stdout.decode('utf-8')),
str(stderr.decode('utf-8')))

@staticmethod
async def include_source_files(platform_id: str,
libraries: Set[str],
target_directory: str) -> None:
"""Include source files from platform's \
library directory to target directory."""
path = os.path.join(LIBRARY_PATH, f'{platform_id}/')
path_to_libs = set([os.path.join(path, library)
for library in libraries])
await asyncio.create_subprocess_exec('cp',
*path_to_libs,
target_directory,
cwd=BUILD_DIRECTORY)

@staticmethod
async def includeLibraryFiles(
libraries: Set[str],
target_directory: str,
extension: str,
platform: str) -> None:
"""Функция, которая копирует все необходимые файлы библиотек."""
"""(Legacy, use include_source_files) \
Функция, которая копирует все необходимые файлы библиотек."""
paths_to_libs = [''.join(
[
f'{Compiler._path(platform)}source/',
f'{Compiler._path(platform)}/',
library,
extension]
) for library in libraries]
Expand Down
35 changes: 21 additions & 14 deletions compiler/PlatformManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from aiopath import AsyncPath

try:
from .types.platform_types import Platform, UnprocessedPlatform
from .types.platform_types import Platform
except ImportError:
from compiler.types.platform_types import Platform, UnprocessedPlatform
from compiler.types.platform_types import Platform


class PlatformException(Exception):
Expand All @@ -27,21 +27,28 @@ class PlatformManager:
platforms: dict[str, Platform] = {}

@staticmethod
async def initPlatform(path_to_schemas_dir: str) -> None:
async def load_platform(path_to_platform: str | AsyncPath) -> None:
"""Load platform from file and add it to dict."""
try:
async with async_open(path_to_platform, 'r') as f:
unprocessed_platform_data: str = await f.read()
platform = Platform(
**json.loads(unprocessed_platform_data))
if PlatformManager.platforms.get(platform.id, None) is None:
PlatformManager.platforms[platform.id] = platform
else:
print(f'Platform with id {platform.id} is already exists.')
except Exception as e:
print(
f'Во время обработки файла "{path_to_platform}"'
f'произошла ошибка! {e}')

@staticmethod
async def init_platforms(path_to_schemas_dir: str) -> None:
"""Find platforms in path and add it to Dict."""
print(f'Поиск схем в папке "{path_to_schemas_dir}"...')
async for path in AsyncPath(path_to_schemas_dir).glob('*json'):
try:
async with async_open(file_specifier=path, mode='r') as f:
unprocessed_platform_data = await f.read()
platform_data = UnprocessedPlatform(
**json.loads(unprocessed_platform_data))
platform_id = list(platform_data.platform.keys())[0]
platform = platform_data.platform[platform_id]
PlatformManager.platforms[platform_id] = platform
except Exception as e:
print(
f'Во время обработки файла "{path}" произошла ошибка! {e}')
await PlatformManager.load_platform(path)

print(
f'Были найдены платформы: {list(PlatformManager.platforms.keys())}'
Expand Down
2 changes: 1 addition & 1 deletion compiler/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
BASE_DIRECTORY = MODULE_PATH + '/' # "server/"
BUILD_DIRECTORY = '/tmp/lapki-compiler/'
LIBRARY_PATH = os.path.join(MODULE_PATH, 'library/')
SCHEMA_DIRECTORY = os.path.join(MODULE_PATH, 'schemas/')
PLATFORM_DIRECTORY = os.path.join(MODULE_PATH, 'platforms/')
LOG_PATH = 'logs.log' # Замените на нужную папку
MAX_MSG_SIZE = 1024 * 50 # Максимальный размер сообщения от клиента.
17 changes: 0 additions & 17 deletions compiler/fullgraphmlparser/.idea/fullgraphmlparser.iml

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions compiler/fullgraphmlparser/.idea/misc.xml

This file was deleted.

8 changes: 0 additions & 8 deletions compiler/fullgraphmlparser/.idea/modules.xml

This file was deleted.

This file was deleted.

6 changes: 0 additions & 6 deletions compiler/fullgraphmlparser/.idea/vcs.xml

This file was deleted.

3 changes: 0 additions & 3 deletions compiler/fullgraphmlparser/__init__.py

This file was deleted.

Loading
Loading