Numworks Epsilon  1.4.1
Graphing Calculator Operating System
port.cpp
Go to the documentation of this file.
1 #include "port.h"
2 
3 #include <ion/keyboard.h>
4 
5 #include <stdint.h>
6 #include <string.h>
7 #include <setjmp.h>
8 
9 extern "C" {
10 #include "py/builtin.h"
11 #include "py/compile.h"
12 #include "py/gc.h"
13 #include "py/lexer.h"
14 #include "py/mperrno.h"
15 #include "py/mphal.h"
16 #include "py/nlr.h"
17 #include "py/repl.h"
18 #include "py/runtime.h"
19 #include "py/stackctrl.h"
20 }
21 
22 static MicroPython::ScriptProvider * sScriptProvider = nullptr;
23 static MicroPython::ExecutionEnvironment * sCurrentExecutionEnvironment = nullptr;
24 
26  m_sandboxIsDisplayed(false)
27 {
28 }
29 
31  return sCurrentExecutionEnvironment;
32 }
33 
35  assert(sCurrentExecutionEnvironment == nullptr);
36  sCurrentExecutionEnvironment = this;
37 
38  nlr_buf_t nlr;
39  if (nlr_push(&nlr) == 0) {
40  mp_lexer_t *lex = mp_lexer_new_from_str_len(0, str, strlen(str), false);
42  mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, true);
44  mp_call_function_0(module_fun);
45  mp_hal_set_interrupt_char(-1); // Disable interrupt
46  nlr_pop();
47  } else { // Uncaught exception
48  /* mp_obj_print_exception is supposed to handle error printing. However,
49  * because we want to print custom information, we copied and modified the
50  * content of mp_obj_print_exception instead of calling it. */
52  size_t n, *values;
54  if (n > 0) {
55  assert(n % 3 == 0);
56  for (int i = n - 3; i >= 0; i -= 3) {
57  if (values[i] != 0 || i == 0) {
58  if (values[i] == 0) {
59  mp_printf(&mp_plat_print, " Last command\n");
60  } else {
61 #if MICROPY_ENABLE_SOURCE_LINE
62  mp_printf(&mp_plat_print, " File \"%q\", line %d", values[i], (int)values[i + 1]);
63 #else
64  mp_printf(&mp_plat_print, " File \"%q\"", values[i]);
65 #endif
66  // the block name can be NULL if it's unknown
67  qstr block = values[i + 2];
68  if (block == MP_QSTR_NULL) {
70  } else {
71  mp_printf(&mp_plat_print, ", in %q\n", block);
72  }
73  }
74  }
75  }
76  }
77  }
80  /* End of mp_obj_print_exception. */
81  }
82 
83  assert(sCurrentExecutionEnvironment == this);
84  sCurrentExecutionEnvironment = nullptr;
85 }
86 
87 extern "C" {
88  extern const void * _stack_start;
89  extern const void * _stack_end;
90 }
91 
92 void MicroPython::init(void * heapStart, void * heapEnd) {
93 #if MP_PORT_USE_STACK_SYMBOLS
96 #else
97  volatile int stackTop;
98  mp_stack_set_top((void *)(&stackTop));
99  mp_stack_set_limit(4000);
100 #endif
101  gc_init(heapStart, heapEnd);
102  mp_init();
103 }
104 
106  mp_deinit();
107 }
108 
110  sScriptProvider = s;
111 }
112 
113 void gc_collect(void) {
114  void * python_stack_top = MP_STATE_THREAD(stack_top);
115  assert(python_stack_top != NULL);
116 
118 
119  /* get the registers.
120  * regs is the also the last object on the stack so the stack is bound by
121  * &regs and python_stack_top. */
122  jmp_buf regs;
123  setjmp(regs);
124 
125  void **regs_ptr = (void**)&regs;
126 
127  /* On the device, the stack is stored in reverse order, but it might not be
128  * the case on a computer. We thus have to take the absolute value of the
129  * addresses difference. */
130  size_t stackLength;
131  if ((uintptr_t)python_stack_top > (uintptr_t)&regs) {
132  stackLength = ((uintptr_t)python_stack_top - (uintptr_t)&regs) / sizeof(uintptr_t);
133  gc_collect_root(regs_ptr, stackLength);
134  } else {
135  stackLength = ((uintptr_t)(&regs) - (uintptr_t)python_stack_top) / sizeof(uintptr_t);
136  gc_collect_root((void **)python_stack_top, stackLength);
137  }
138 
139  gc_collect_end();
140 }
141 
142 void nlr_jump_fail(void *val) {
143  while (1);
144 }
145 
146 mp_lexer_t * mp_lexer_new_from_file(const char * filename) {
147  if (sScriptProvider != nullptr) {
148  const char * script = sScriptProvider->contentOfScript(filename);
149  if (script != nullptr) {
150  return mp_lexer_new_from_str_len(qstr_from_str(filename), script, strlen(script), 0 /* size_t free_len*/);
151  } else {
153  }
154  } else {
156  }
157 }
158 
159 mp_import_stat_t mp_import_stat(const char *path) {
160  if (sScriptProvider && sScriptProvider->contentOfScript(path)) {
161  return MP_IMPORT_STAT_FILE;
162  }
164 }
165 
166 void mp_hal_stdout_tx_strn_cooked(const char * str, size_t len) {
167  assert(sCurrentExecutionEnvironment != nullptr);
168  sCurrentExecutionEnvironment->printText(str, len);
169 }
170 
171 const char * mp_hal_input(const char * prompt) {
172  assert(sCurrentExecutionEnvironment != nullptr);
173  return sCurrentExecutionEnvironment->inputText(prompt);
174 }
const mp_print_t mp_plat_print
Definition: mpprint.c:51
void gc_collect(void)
Definition: port.cpp:113
static ExecutionEnvironment * currentExecutionEnvironment()
Definition: port.cpp:30
bool mp_obj_is_exception_instance(mp_obj_t self_in)
Definition: objexcept.c:451
void runCode(const char *)
Definition: port.cpp:34
#define assert(e)
Definition: assert.h:9
void gc_init(void *start, void *end)
void init(void *heapStart, void *heapEnd)
Definition: port.cpp:92
virtual const char * contentOfScript(const char *name)=0
void mp_init(void)
Definition: runtime.c:58
#define nlr_push(buf)
Definition: nlr.h:73
virtual const char * inputText(const char *prompt)
Definition: port.h:20
int setjmp(jmp_buf env)
mp_lexer_t * mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len)
int mp_print_str(const mp_print_t *print, const char *str)
Definition: mpprint.c:53
unsigned int uintptr_t
Definition: stdint.h:14
mp_import_stat_t mp_import_stat(const char *path)
Definition: port.cpp:159
qstr qstr_from_str(const char *str)
Definition: qstr.c:183
LIBA_BEGIN_DECLS typedef int jmp_buf[31]
Definition: setjmp.h:17
void gc_collect_start(void)
#define MP_STATE_THREAD(x)
Definition: mpstate.h:248
mp_obj_t mp_call_function_0(mp_obj_t fun)
Definition: runtime.c:599
#define MP_ENOENT
Definition: mperrno.h:92
mp_lexer_t * mp_lexer_new_from_file(const char *filename)
Definition: port.cpp:146
const void * _stack_start
void mp_deinit(void)
Definition: runtime.c:130
const char * mp_hal_input(const char *prompt)
Definition: port.cpp:171
const void * _stack_end
size_t strlen(const char *s)
Definition: strlen.c:3
#define mp_stack_set_limit(limit)
Definition: stackctrl.h:43
mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl)
void gc_collect_root(void **ptrs, size_t len)
#define NULL
Definition: stddef.h:4
void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values)
Definition: objexcept.c:537
NORETURN void mp_raise_OSError(int errno_)
Definition: runtime.c:1464
void registerScriptProvider(ScriptProvider *s)
Definition: port.cpp:109
void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind)
Definition: obj.c:59
size_t qstr
Definition: qstr.h:48
void gc_collect_end(void)
#define false
Definition: stdbool.h:9
#define nlr_pop()
Definition: nlr.h:74
void * ret_val
Definition: nlr.h:42
mp_parse_tree_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind)
virtual void printText(const char *text, size_t length)
Definition: port.h:25
void deinit()
Definition: port.cpp:105
void mp_hal_set_interrupt_char(int c)
void nlr_jump_fail(void *val)
Definition: port.cpp:142
Definition: nlr.h:39
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len)
Definition: port.cpp:166
uint64_t mp_obj_t
Definition: obj.h:39
int mp_printf(const mp_print_t *print, const char *fmt,...)
Definition: mpprint.c:380
Definition: obj.h:415
qstr source_name
Definition: lexer.h:149
void mp_stack_set_top(void *top)
Definition: stackctrl.c:38
mp_import_stat_t
Definition: lexer.h:182