-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompiler.py
179 lines (154 loc) · 6.69 KB
/
compiler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import os
import logging
import io
from pydantic import BaseModel
from fastapi import APIRouter, Request, Depends
import sqlalchemy
from satop_platform.plugin_engine.plugin import Plugin
from satop_platform.components.syslog import models
from proc_comp.parser import parser
from proc_comp.codegen.codegen import CodeGen
from uuid import UUID
logger = logging.getLogger('plugin.compilor')
class FlightPlanInstructions(BaseModel):
instructions: dict
model_config = {
"json_schema_extra": {
"examples": [
{
"instructions":
{
"name": "commands",
"body": [
{
"name": "repeat-n",
"count": 10,
"body": [
{
"name": "gpio-write",
"pin": 16,
"value": 1
},
{
"name": "wait-sec",
"duration": 1
},
{
"name": "gpio-write",
"pin": 16,
"value": 0
},
{
"name": "wait-sec",
"duration": 1
}
]
}
]
}
}
]
}
}
class CompiledInstructions(BaseModel):
instructions: list
artifact_id: str
model_config = {
"json_schema_extra": {
"examples": [
{
"instructions": [
"gpio_write(16, 1);",
"wait_sec(1);",
"gpio_write(16, 0);",
"wait_sec(1);"
],
"artifact_id": "b7f1c0b9b6f3b2e1f0c0b9b6f3b2e1f0"
}
]
}
}
class Compiler(Plugin):
def __init__(self, *args, **kwargs):
plugin_dir = os.path.dirname(os.path.realpath(__file__))
super().__init__(plugin_dir, *args, **kwargs)
if not self.check_required_capabilities(['http.add_routes']):
raise RuntimeError
self.api_router = APIRouter()
# super().register_function('compile', self.compile)
# Send in JSON and return compiled code
@self.api_router.post(
'/compile',
summary="Compile a flight plan into CSH.",
description="Takes a flight plan and compiles it into CSH. The flight plan is a JSON object that describes the sequence of commands to be executed and MUST start with 'instructions: {the instructions in question}'.",
response_description="The compiled code and artifact ID for the compiled code.",
status_code=201,
dependencies=[Depends(self.platform_auth.require_login)]
)
async def new_compile(flight_plan_instructions:FlightPlanInstructions, request: Request) -> CompiledInstructions:
comiled_plan, compiled_artifact_id = await self.compile(flight_plan=flight_plan_instructions.instructions, user_id=request.state.userid)
return CompiledInstructions(
instructions = comiled_plan,
artifact_id= compiled_artifact_id
)
def startup(self):
super().startup()
logger.info("Running Compilor statup protocol")
def shutdown(self):
super().shutdown()
logger.info(f"'{self.name}' Shutting down gracefully")
@Plugin.register_function
async def compile(self, flight_plan:dict, user_id:str):
"""Compile a flight plan into CSH
Args:
flight_plan (dict): The flight plan to be compiled.
user_id (str): The ID of the user who submitted the flight plan.
Returns:
(list(dict, UUID)): The compiled code and artifact ID for the compiled code.
"""
# Send in JSON and return compiled code
flight_plan_as_bytes = io.BytesIO(str(flight_plan).encode('utf-8'))
try:
artifact_in_id = self.sys_log.create_artifact(flight_plan_as_bytes, filename='flight_plan.json').sha1
logger.info(f"Received new flight plan with artifact ID: {artifact_in_id}")
except sqlalchemy.exc.IntegrityError as e:
# Artifact already exists
artifact_in_id = e.params[0]
logger.info(f"Received existing flight plan with artifact ID: {artifact_in_id}")
## --- Do the actual compilation here ---
p = parser.parse(flight_plan)
if p is None:
return {"message": "Error parsing flight plan"}
G = CodeGen()
compiled = G.code_gen(p)
## --- End of compilation ---
compiled_as_bytes = "\n".join(compiled).encode('utf-8')
try:
artifact_out_id = self.sys_log.create_artifact(io.BytesIO(compiled_as_bytes), filename='flight_plan.csh').sha1
except sqlalchemy.exc.IntegrityError as e:
# Artifact already exists
artifact_out_id = e.params[0]
self.sys_log.log_event(models.Event(
descriptor='CSHCompileEvent',
relationships=[
models.EventObjectRelationship(
predicate=models.Predicate(descriptor='startedBy'),
object=models.Entity(type=models.EntityType.user, id=user_id)
),
models.EventObjectRelationship(
predicate=models.Predicate(descriptor='used'),
object=models.Artifact(sha1=artifact_in_id)
),
models.EventObjectRelationship(
predicate=models.Predicate(descriptor='created'),
object=models.Artifact(sha1=artifact_out_id)
),
models.Triple(
subject=models.Artifact(sha1=artifact_out_id),
predicate=models.Predicate(descriptor='generatedFrom'),
object=models.Artifact(sha1=artifact_in_id)
)
]
))
logger.info(f"Compiled flight_plan with ID: {artifact_in_id} into CSH with ID: {artifact_out_id}")
return compiled, artifact_out_id