Skip to content

Commit 823c14e

Browse files
committed
Refactor lua code generation
1 parent 92df874 commit 823c14e

File tree

16 files changed

+115
-101
lines changed

16 files changed

+115
-101
lines changed

computercraft/errors.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
11
class LuaException(Exception):
22
pass
3-
4-
5-
class ApiException(Exception):
6-
pass

computercraft/lua.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from typing import Union
2+
3+
4+
LuaTable = Union[list, dict]
5+
LuaNum = Union[int, float]
6+
7+
8+
class LuaExpr:
9+
def get_expr_code(self):
10+
raise NotImplementedError
11+
12+
13+
def lua_string(v):
14+
return '"{}"'.format(
15+
v.replace('\\', '\\\\')
16+
.replace('\a', '\\a')
17+
.replace('\b', '\\b')
18+
.replace('\f', '\\f')
19+
.replace('\n', '\\n')
20+
.replace('\r', '\\r')
21+
.replace('\t', '\\t')
22+
.replace('\v', '\\v')
23+
.replace('"', '\\"')
24+
.replace("'", "\\'")
25+
.replace('[', '\\[')
26+
.replace(']', '\\]')
27+
)
28+
29+
30+
def lua_list(v):
31+
return '{' + ', '.join(lua_value(x) for x in v) + '}'
32+
33+
34+
def lua_dict(v):
35+
return '{' + ', '.join(
36+
'[{}]={}'.format(lua_value(k), lua_value(v)) for k, v in v.items()
37+
) + '}'
38+
39+
40+
def lua_value(v):
41+
if v is None:
42+
return 'nil'
43+
if v is False:
44+
return 'false'
45+
if v is True:
46+
return 'true'
47+
if isinstance(v, str):
48+
return lua_string(v)
49+
if isinstance(v, (int, float)):
50+
return str(v)
51+
if isinstance(v, list):
52+
return lua_list(v)
53+
if isinstance(v, dict):
54+
return lua_dict(v)
55+
if isinstance(v, LuaExpr):
56+
return v.get_expr_code()
57+
raise ValueError('Can\'t convert a value to lua {}'.format(v))
58+
59+
60+
def lua_args(*params, omit_nulls=True):
61+
if omit_nulls:
62+
for idx in range(len(params) - 1, -1, -1):
63+
if params[idx] is not None:
64+
break
65+
else:
66+
idx = -1
67+
params = params[:idx + 1]
68+
return ', '.join(lua_value(p) for p in params)

computercraft/server.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _new_task_id(self) -> str:
103103
self._task_autoid += 1
104104
return task_id
105105

106-
async def raw_eval(self, lua_code, immediate=False):
106+
async def _eval(self, lua_code, immediate=False):
107107
task_id = self._new_task_id()
108108
self._result_locks[task_id] = asyncio.Event()
109109
await self._cmd.put({
@@ -118,11 +118,11 @@ async def raw_eval(self, lua_code, immediate=False):
118118
print('{} → {}'.format(lua_code, repr(result)))
119119
return result
120120

121-
async def raw_eval_coro(self, lua_code):
122-
return rproc.coro(await self.raw_eval(lua_code))
121+
async def eval(self, lua_code):
122+
return await self._eval(lua_code, True)
123123

124-
async def _send_cmd(self, lua):
125-
return await self.raw_eval_coro(lua)
124+
async def eval_coro(self, lua_code):
125+
return rproc.coro(await self._eval(lua_code, False))
126126

127127
async def _start_queue(self, event):
128128
task_id = self._new_task_id()

computercraft/subapis/base.py

Lines changed: 2 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,4 @@
1-
from ..errors import ApiException
2-
from typing import Union
3-
4-
5-
LuaTable = Union[list, dict]
6-
LuaNum = Union[int, float]
7-
8-
9-
def lua_string(v):
10-
return '"{}"'.format(
11-
v.replace('\\', '\\\\')
12-
.replace('\a', '\\a')
13-
.replace('\b', '\\b')
14-
.replace('\f', '\\f')
15-
.replace('\n', '\\n')
16-
.replace('\r', '\\r')
17-
.replace('\t', '\\t')
18-
.replace('\v', '\\v')
19-
.replace('"', '\\"')
20-
.replace("'", "\\'")
21-
.replace('[', '\\[')
22-
.replace(']', '\\]')
23-
)
24-
25-
26-
def lua_list(v):
27-
return '{' + ', '.join(lua_value(x) for x in v) + '}'
28-
29-
30-
def lua_dict(v):
31-
return '{' + ', '.join(
32-
'[{}]={}'.format(lua_value(k), lua_value(v)) for k, v in v.items()
33-
) + '}'
34-
35-
36-
def lua_value(v):
37-
if v is None:
38-
return 'nil'
39-
if v is False:
40-
return 'false'
41-
if v is True:
42-
return 'true'
43-
if isinstance(v, str):
44-
return lua_string(v)
45-
if isinstance(v, (int, float)):
46-
return str(v)
47-
if isinstance(v, list):
48-
return lua_list(v)
49-
if isinstance(v, dict):
50-
return lua_dict(v)
51-
raise ValueError('Can\'t convert a value to lua {}'.format(v))
52-
53-
54-
def lua_args(*params, omit_nulls=True):
55-
ps, can_add = [], True
56-
for p in params:
57-
if omit_nulls and p is None:
58-
can_add = False
59-
continue
60-
if not can_add:
61-
raise ApiException('Optional parameter order error')
62-
ps.append(lua_value(p))
63-
return ', '.join(ps)
1+
from ..lua import lua_args
642

653

664
class BaseSubAPI:
@@ -70,6 +8,6 @@ def __init__(self, cc):
708
self._cc = cc
719

7210
async def _send(self, method, *params, omit_nulls=True):
73-
return await self._cc._send_cmd('return {}.{}({})'.format(
11+
return await self._cc.eval_coro('return {}.{}({})'.format(
7412
self._API, method, lua_args(*params, omit_nulls=omit_nulls)
7513
))

computercraft/subapis/fs.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from contextlib import asynccontextmanager
22
from typing import Optional, List
33

4-
from .base import BaseSubAPI, lua_string
4+
from .base import BaseSubAPI
5+
from ..lua import LuaExpr, lua_string
56
from ..rproc import boolean, string, integer, nil, array_string, option_string, fact_scheme_dict
67

78

@@ -13,11 +14,14 @@
1314
}, {})
1415

1516

16-
class BaseHandle(BaseSubAPI):
17+
class BaseHandle(BaseSubAPI, LuaExpr):
1718
def __init__(self, cc, var):
1819
super().__init__(cc)
1920
self._API = var
2021

22+
def get_expr_code(self):
23+
return self._API
24+
2125

2226
class ReadHandle(BaseHandle):
2327
async def read(self, count: int) -> Optional[str]:
@@ -106,12 +110,12 @@ async def open(self, path: str, mode: str):
106110
'''
107111
fid = self._cc._new_task_id()
108112
var = 'temp[{}]'.format(lua_string(fid))
109-
await self._cc._send_cmd('{} = fs.open({}, {})'.format(
113+
await self._cc.eval_coro('{} = fs.open({}, {})'.format(
110114
var, *map(lua_string, [path, mode])))
111115
try:
112116
yield (ReadHandle if 'r' in mode else WriteHandle)(self._cc, var)
113117
finally:
114-
await self._cc._send_cmd('{}.close(); {} = nil'.format(var, var))
118+
await self._cc.eval_coro('{}.close(); {} = nil'.format(var, var))
115119

116120
async def find(self, wildcard: str) -> List[str]:
117121
return array_string(await self._send('find', wildcard))

computercraft/subapis/gps.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Tuple, Optional
22

3-
from .base import BaseSubAPI, LuaNum
3+
from .base import BaseSubAPI
4+
from ..lua import LuaNum
45
from ..rproc import tuple3_number, fact_option
56

67

computercraft/subapis/keys.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Optional
22

3-
from .base import BaseSubAPI, lua_string
3+
from .base import BaseSubAPI
4+
from ..lua import lua_string
45
from ..rproc import option_integer, option_string
56

67

@@ -10,7 +11,7 @@ class KeysAPI(BaseSubAPI):
1011
async def getCode(self, name: str) -> Optional[int]:
1112
# replaces properties
1213
# keys.space → await api.keys.getCode('space')
13-
return option_integer(await self._cc._send_cmd('''
14+
return option_integer(await self._cc.eval_coro('''
1415
if type({api}[{key}]) == 'number' then
1516
return {api}[{key}]
1617
end
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from typing import List
2-
31
from .base import BaseSubAPI
42
from ..rproc import integer, string, nil, boolean
53

@@ -13,17 +11,19 @@ async def getCurrent(self) -> int:
1311
async def getCount(self) -> int:
1412
return integer(await self._send('getCount'))
1513

16-
async def launch(self, environment: dict, programPath: str, *args: List[str]) -> int:
14+
async def launch(self, programPath: str, *args: str, environment: dict = None) -> int:
15+
if environment is None:
16+
environment = {}
1717
return integer(await self._send('launch', environment, programPath, *args))
1818

19-
async def setFocus(self, tabID: int):
20-
return boolean(await self._send('setFocus', tabID))
21-
2219
async def setTitle(self, tabID: int, title: str):
2320
return nil(await self._send('setTitle', tabID, title))
2421

2522
async def getTitle(self, tabID: int) -> str:
2623
return string(await self._send('getTitle', tabID))
2724

25+
async def setFocus(self, tabID: int):
26+
return boolean(await self._send('setFocus', tabID))
27+
2828
async def getFocus(self) -> int:
2929
return integer(await self._send('getFocus'))

computercraft/subapis/os.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from contextlib import asynccontextmanager
22
from typing import Optional, List
33

4-
from .base import BaseSubAPI, LuaTable, LuaNum
4+
from .base import BaseSubAPI
5+
from ..lua import LuaTable, LuaNum
56
from ..rproc import nil, string, option_string, number, integer, boolean
67

78

computercraft/subapis/peripheral.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
from dataclasses import dataclass
33
from typing import Optional, List, Tuple, Any, Union
44

5-
from .base import BaseSubAPI, LuaNum
5+
from .base import BaseSubAPI
66
from .mixins import TermMixin
7+
from ..lua import LuaNum
78
from ..rproc import (
89
boolean, nil, integer, string, option_integer, option_string,
910
tuple2_integer, array_string, option_string_bool, try_result,

0 commit comments

Comments
 (0)