SayoriOS  0.3.3
elk.h
1 #ifndef SAYORI_ELK_H
2 #define SAYORI_ELK_H
3 #pragma once
4 
5 #include "common.h"
6 #include "ext/jse_canvas.h"
7 #include "ext/jse_event.h"
8 #include "ext/jse_array.h"
9 
10 typedef int double_t; // Тип данных для чисел
11 
12 struct js; // Движок JS (непрозрачный)
13 typedef uint64_t jsval_t; // Типы данных хранящие значения JS
14 
15 struct js *js_create(void *buf, size_t len); // Создать экземпляр JS
16 jsval_t js_eval(struct js *, const char *, size_t); // Выполнить JS-код
17 jsval_t js_glob(struct js *); // Возвращает глобальный объект
18 const char *js_str(struct js *, jsval_t val); // Stringify JS value
19 bool js_chkargs(jsval_t *, int, const char *); // Проверяет правильность аргументов
20 bool js_truthy(struct js *, jsval_t); // Проверьте, является ли значение истинным
21 void js_setmaxcss(struct js *, size_t); // Установите максимальный размер стека
22 void js_setgct(struct js *, size_t); // Установите порог срабатывания GC
23 void js_stats(struct js *, size_t *total, size_t *min, size_t *cstacksize);
24 void js_dump(struct js *); // Выводит отладочную информацию.
25 void js_statsInfo(struct js *js); // Печает в консоль результаты выполнения JS экземпляра
26 
27 // Создайте значения JS из значений C
28 jsval_t js_mkundef(void); // Создать undefined
29 jsval_t js_mknull(void); // Создать null, null, true, false
30 jsval_t js_mktrue(void); // Создать true
31 jsval_t js_mkfalse(void); // Создать false
32 jsval_t js_mkstr(struct js *, const void *, size_t); // Создать строку
33 jsval_t js_mknum(double_t); // Создать число
34 jsval_t js_mkerr(struct js *js, const char *fmt, ...); // Создать error
35 jsval_t js_mkfun(jsval_t (*fn)(struct js *, jsval_t *, int)); // Создать функцию
36 jsval_t js_mkobj(struct js *); // Создать объект
37 void js_set(struct js *, jsval_t, const char *, jsval_t); // Установить object attr
38 
39 enum { JS_UNDEF, JS_NULL, JS_TRUE, JS_FALSE, JS_STR, JS_NUM, JS_ERR, JS_PRIV };
40 int js_type(jsval_t val); // Возвращает тип JS-значения
41 double_t js_getnum(jsval_t val); // Получить число
42 int js_getbool(jsval_t val); // Получить boolean, 0 or 1
43 char *js_getstr(struct js *js, jsval_t val, size_t *len); // Получить строку
44 
45 
46 typedef uint32_t jsoff_t;
47 
48 struct js {
49  jsoff_t css; // Максимальный наблюдаемый размер стека C
50  jsoff_t lwm; // JS RAM low watermark: наблюдается минимальное количество свободной оперативной памяти
51  const char *code; // Анализируемый в данный момент фрагмент кода (весь код, который выполняется)
52  char errmsg[33]; // Сообщение об ошибке
53  uint8_t isFatal; // Выполнение закончилось ошибкой?
54  uint8_t tok; // Последнее проанализированное значение токена
55  uint8_t consumed; // Индикатор того, что был использован последний проанализированный токен
56  uint8_t flags; // Флаги выполнения, смотрите константы F_* ниже
57 #define F_NOEXEC 1U // Разбирать код, но не выполнять
58 #define F_LOOP 2U // Код выполняется внутри петли
59 #define F_CALL 4U // Код выполняется внутри вызова функции
60 #define F_BREAK 8U // Выход из цикла
61 #define F_RETURN 16U // Был выполнен возврат из функции
62  jsoff_t clen; // Длина фрагмента кода
63  jsoff_t pos; // Текущая позиция синтаксического анализа
64  jsoff_t toff; // Смещение последнего проанализированного токена
65  jsoff_t tlen; // Длина последнего проанализированного токена
66  jsoff_t nogc; // Смещение объекта для исключения из GC
67  jsval_t tval; // Содержит последнее проанализированное числовое или строковое литеральное значение
68  jsval_t scope; // Текущая область применения
69  uint8_t *mem; // Доступная память JS
70  jsoff_t size; // Объем памяти JS
71  jsoff_t brk; // Текущая граница использования mem
72  jsoff_t gct; // Порог GC. Если brk > gct, запустите GC
73  jsoff_t maxcss; // Максимально допустимый размер использования стека C
74  jsoff_t incSize; // Размер загруженных библиотек
75  jsoff_t paramSize; // Кол-во просканированных параметров JSE CF
76  JSE_CANVAS Canvas; // [JSE] [EXT] [Canvas]
77  void *cstk; // Указатель стека C в начале js_eval()
78 };
79 
80 // В памяти JS хранятся различные сущности: объекты, свойства, строки
81 // Все объекты упаковываются в начало буфера.
82 // `brk` обозначает конец используемой памяти:
83 //
84 // | entity1 | entity2| .... |entityN| неиспользуемая память |
85 // |---------|--------|------|-------|------------------------------|
86 // js.mem js.brk js.size
87 //
88 // Каждый объект выровнен по 4 байтам, поэтому 2 бита LSB хранят тип объекта.
89 // Объект: 8 байт: смещение первого свойства, смещение верхнего объекта
90 // Свойство: 8 байт + значение val: 4 байта следующего пропа, 4 байта отстува, N байт значения
91 // Строка: 4xN байт: 4 байта len << 2, 4 байта выровненных по 0-завершенных данных
92 //
93 // Если импортируются функции C, они используют верхнюю часть памяти в качестве стека для передачи параметров.
94 // Каждый аргумент помещается в верхнюю часть памяти как jsval_t, а js.size уменьшается на sizeof(jsval_t), т.е. на 8 байт.
95 // Когда функция возвращается, js.size восстанавливается обратно.
96 // Таким образом, js.size используется в качестве указателя стека.
97 
98 enum {
99  TOK_ERR, TOK_EOF, TOK_IDENTIFIER, TOK_NUMBER, TOK_STRING, TOK_SEMICOLON,
100  TOK_LPAREN, TOK_RPAREN, TOK_LBRACE, TOK_RBRACE,
101  // Keyword tokens
102  TOK_BREAK = 50, TOK_CASE, TOK_CATCH, TOK_CLASS, TOK_CONST, TOK_CONTINUE,
103  TOK_DEFAULT, TOK_DELETE, TOK_DO, TOK_ELSE, TOK_FINALLY, TOK_FOR, TOK_FUNC,
104  TOK_IF, TOK_IN, TOK_INSTANCEOF, TOK_LET, TOK_NEW, TOK_RETURN, TOK_SWITCH,
105  TOK_THIS, TOK_THROW, TOK_TRY, TOK_VAR, TOK_VOID, TOK_WHILE, TOK_WITH,
106  TOK_YIELD, TOK_UNDEF, TOK_NULL, TOK_TRUE, TOK_FALSE,
107  // JS Operator tokens
108  TOK_DOT = 100, TOK_CALL, TOK_POSTINC, TOK_POSTDEC, TOK_NOT, TOK_TILDA, // 100
109  TOK_TYPEOF, TOK_UPLUS, TOK_UMINUS, TOK_EXP, TOK_MUL, TOK_DIV, TOK_REM, // 106
110  TOK_PLUS, TOK_MINUS, TOK_SHL, TOK_SHR, TOK_ZSHR, TOK_LT, TOK_LE, TOK_GT, // 113
111  TOK_GE, TOK_EQ, TOK_NE, TOK_AND, TOK_XOR, TOK_OR, TOK_LAND, TOK_LOR, // 121
112  TOK_COLON, TOK_Q, TOK_ASSIGN, TOK_PLUS_ASSIGN, TOK_MINUS_ASSIGN,
113  TOK_MUL_ASSIGN, TOK_DIV_ASSIGN, TOK_REM_ASSIGN, TOK_SHL_ASSIGN,
114  TOK_SHR_ASSIGN, TOK_ZSHR_ASSIGN, TOK_AND_ASSIGN, TOK_XOR_ASSIGN,
115  TOK_OR_ASSIGN, TOK_COMMA,
116 };
117 
118 enum {
119  // ВАЖНО: T_OBJ, T_PROP, T_STR должны быть запущены первыми.
120  // Этого требуют функции компоновки памяти: типы объектов памяти кодируются в 2 битах,
121  // таким образом, значения типов должны быть 0,1,2,3
122  T_OBJ, T_PROP, T_STR, T_UNDEF, T_NULL, T_NUM, T_BOOL, T_FUNC, T_CODEREF,
123  T_CFUNC, T_ERR
124 };
125 
126 static jsval_t tov(double_t d) {
127  union { double_t d; jsval_t v; } u = {d};
128  return u.v;
129 }
130 static jsval_t tov2(int d) { union { int d; jsval_t v; } u = {d}; return u.v; }
131 static double_t tod(jsval_t v) {
132  union { jsval_t v; double_t d; } u = {v};
133  return u.d;
134 }
135 static double_t tod2(jsval_t v) {
136  union { jsval_t v; int d; } u = {v};
137  return u.d;
138 }
139 static jsval_t mkval(uint8_t type, uint64_t data) { return ((jsval_t) 0x7ff0U << 48U) | ((jsval_t) (type) << 48) | (data & 0xffffffffffffUL); }
140 static bool is_nan(jsval_t v) { return (v >> 52U) == 0x7ffU; }
141 static uint8_t vtype(jsval_t v) { return is_nan(v) ? ((v >> 48U) & 15U) : (uint8_t) T_NUM; }
142 static size_t vdata(jsval_t v) { return (size_t) (v & ~((jsval_t) 0x7fffUL << 48U)); }
143 static jsval_t mkcoderef(jsval_t off, jsoff_t len) { return mkval(T_CODEREF, (off & 0xffffffU) | ((jsval_t)(len & 0xffffffU) << 24U)); }
144 static jsoff_t coderefoff(jsval_t v) { return v & 0xffffffU; }
145 static jsoff_t codereflen(jsval_t v) { return (v >> 24U) & 0xffffffU; }
146 
147 static uint8_t unhex(uint8_t c) { return (c >= '0' && c <= '9') ? (uint8_t) (c - '0') : (c >= 'a' && c <= 'f') ? (uint8_t) (c - 'W') : (c >= 'A' && c <= 'F') ? (uint8_t) (c - '7') : 0; }
148 static bool is_space(int c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == '\f' || c == '\v'; }
149 static bool is_digit(int c) { return c >= '0' && c <= '9'; }
150 static bool is_xdigit(int c) { return is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
151 static bool is_alpha(int c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
152 static bool is_ident_begin(int c) { return c == '_' || c == '$' || is_alpha(c); }
153 static bool is_ident_continue(int c) { return c == '_' || c == '$' || is_alpha(c) || is_digit(c); }
154 static bool is_err(jsval_t v) { return vtype(v) == T_ERR; }
155 static bool is_unary(uint8_t tok) { return tok >= TOK_POSTINC && tok <= TOK_UMINUS; }
156 static bool is_assign(uint8_t tok) { return (tok >= TOK_ASSIGN && tok <= TOK_OR_ASSIGN); }
157 static void saveoff(struct js *js, jsoff_t off, jsoff_t val) { memcpy(&js->mem[off], &val, sizeof(val)); }
158 static void saveval(struct js *js, jsoff_t off, jsval_t val) { memcpy(&js->mem[off], &val, sizeof(val)); }
159 static jsoff_t loadoff(struct js *js, jsoff_t off) { jsoff_t v = 0; passert(js->brk <= js->size); memcpy(&v, &js->mem[off], sizeof(v)); return v; }
160 static jsoff_t offtolen(jsoff_t off) { return (off >> 2) - 1; }
161 static jsoff_t vstrlen(struct js *js, jsval_t v) { return offtolen(loadoff(js, (jsoff_t) vdata(v))); }
162 static jsval_t loadval(struct js *js, jsoff_t off) { jsval_t v = 0; memcpy(&v, &js->mem[off], sizeof(v)); return v; }
163 static jsval_t upper(struct js *js, jsval_t scope) { return mkval(T_OBJ, loadoff(js, (jsoff_t) (vdata(scope) + sizeof(jsoff_t)))); }
164 static jsoff_t align32(jsoff_t v) { return ((v + 3) >> 2) << 2; }
165 
166 #define CHECKV(_v) do { if (is_err(_v)) { res = (_v); goto done; } } while (0)
167 #define EXPECT(_tok, _e) do { if (next(js) != _tok) { _e; return js_mkerr(js, "parse error"); }; js->consumed = 1; } while (0)
168 
169 static size_t tostr(struct js *js, jsval_t value, char *buf, size_t len);
170 static jsval_t js_expr(struct js *js);
171 static jsval_t js_stmt(struct js *js);
172 static jsval_t do_op(struct js *, uint8_t op, jsval_t l, jsval_t r);
173 
174 void jse_file_getBuff(char* buf);
175 JSE_ARRAY* js_getObjectToArray(struct js *js, jsval_t value);
176 
177 
178 jsval_t elk_call_js_fnc(struct js *js, const char *fn, jsoff_t fnlen);
179 
180 #include "ext/jse_function.h"
181 
182 #endif //SAYORI_ELK_H
Основные определения ядра
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
Структура массива
Definition: jse_array.h:40
Definition: elk.h:48