mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-03-04 05:05:57 +08:00
term library added
This commit is contained in:
parent
052f1e263e
commit
da6105d46c
@ -485,12 +485,6 @@ struct Compiler {
|
||||
// such assignments.
|
||||
bool can_define;
|
||||
|
||||
// This value will set to true for parsing a temproary expression
|
||||
// (ie. if <expr> ...) and the value of the expression will be popped out of
|
||||
// the stack onece we're done, if it's a defenition, that value should be
|
||||
// duplicated on the stack to prevent it.
|
||||
bool expr_temp;
|
||||
|
||||
// This value will be true after parsing a call expression, for every other
|
||||
// Expressions it'll be false. This is **ONLY** to be used when compiling a
|
||||
// return statement to check if the last parsed expression is a call to
|
||||
@ -1896,13 +1890,10 @@ static void exprInterpolation(Compiler* compiler) {
|
||||
|
||||
static void exprFunction(Compiler* compiler) {
|
||||
bool can_define = compiler->can_define;
|
||||
bool expr_temp = compiler->expr_temp;
|
||||
|
||||
compiler->can_define = true;
|
||||
compiler->expr_temp = false;
|
||||
compileFunction(compiler, FUNC_LITERAL);
|
||||
compiler->can_define = can_define;
|
||||
compiler->expr_temp = expr_temp;
|
||||
}
|
||||
|
||||
static void exprName(Compiler* compiler) {
|
||||
@ -1994,10 +1985,6 @@ static void exprName(Compiler* compiler) {
|
||||
ASSERT(compiler->parser.has_errors ||
|
||||
(compiler->func->stack_size - 1) == index, OOPS);
|
||||
|
||||
if (compiler->expr_temp) {
|
||||
emitOpcode(compiler, OP_DUP);
|
||||
}
|
||||
|
||||
} else {
|
||||
// The assigned value or the result of the operator will be at the top of
|
||||
// the stack by now. Store it.
|
||||
@ -3087,10 +3074,10 @@ static void compileIfStatement(Compiler* compiler, bool elif) {
|
||||
|
||||
skipNewLines(compiler);
|
||||
|
||||
bool expr_temp = compiler->expr_temp;
|
||||
compiler->expr_temp = true;
|
||||
bool can_define = compiler->can_define;
|
||||
compiler->can_define = false;
|
||||
compileExpression(compiler); //< Condition.
|
||||
compiler->expr_temp = expr_temp;
|
||||
compiler->can_define = can_define;
|
||||
|
||||
emitOpcode(compiler, OP_JUMP_IF_NOT);
|
||||
int ifpatch = emitShort(compiler, 0xffff); //< Will be patched.
|
||||
@ -3140,10 +3127,10 @@ static void compileWhileStatement(Compiler* compiler) {
|
||||
loop.depth = compiler->scope_depth;
|
||||
compiler->loop = &loop;
|
||||
|
||||
bool expr_temp = compiler->expr_temp;
|
||||
compiler->expr_temp = true;
|
||||
bool can_define = compiler->can_define;
|
||||
compiler->can_define = false;
|
||||
compileExpression(compiler); //< Condition.
|
||||
compiler->expr_temp = expr_temp;
|
||||
compiler->can_define = can_define;
|
||||
|
||||
emitOpcode(compiler, OP_JUMP_IF_NOT);
|
||||
int whilepatch = emitShort(compiler, 0xffff); //< Will be patched.
|
||||
@ -3176,10 +3163,10 @@ static void compileForStatement(Compiler* compiler) {
|
||||
|
||||
// Compile and store sequence.
|
||||
compilerAddVariable(compiler, "@Sequence", 9, iter_line); // Sequence
|
||||
bool expr_temp = compiler->expr_temp;
|
||||
compiler->expr_temp = true;
|
||||
bool can_define = compiler->can_define;
|
||||
compiler->can_define = false;
|
||||
compileExpression(compiler);
|
||||
compiler->expr_temp = expr_temp;
|
||||
compiler->can_define = can_define;
|
||||
|
||||
// Add iterator to locals. It's an increasing integer indicating that the
|
||||
// current loop is nth starting from 0.
|
||||
|
259
src/libs/ext_term.c
Normal file
259
src/libs/ext_term.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022 Thakee Nathees
|
||||
* Copyright (c) 2021-2022 Pocketlang Contributors
|
||||
* Distributed Under The MIT License
|
||||
*/
|
||||
|
||||
#ifndef PK_AMALGAMATED
|
||||
#include "libs.h"
|
||||
#endif
|
||||
|
||||
#define TERM_IMPLEMENT
|
||||
#include "thirdparty/term/term.h" //<< AMALG_INLINE >>
|
||||
#undef TERM_IMPLEMENT
|
||||
|
||||
// A reference to the event class, to check is instance of.
|
||||
static PkHandle* _cls_term_event = NULL;
|
||||
|
||||
static void _setSlotVector(PKVM* vm, int slot, int tmp, double x, double y) {
|
||||
|
||||
if (!pkImportModule(vm, "types", slot)) return;
|
||||
if (!pkGetAttribute(vm, slot, "Vector", slot)) return;
|
||||
if (!pkNewInstance(vm, slot, slot, 0, 0)) return;
|
||||
|
||||
pkSetSlotNumber(vm, tmp, x);
|
||||
if (!pkSetAttribute(vm, slot, "x", tmp)) return;
|
||||
pkSetSlotNumber(vm, tmp, y);
|
||||
if (!pkSetAttribute(vm, slot, "y", tmp)) return;
|
||||
}
|
||||
|
||||
void* _termEventNew(PKVM* vm) {
|
||||
term_Event* event = pkRealloc(vm, NULL, sizeof(term_Event));
|
||||
event->type = TERM_ET_UNKNOWN;
|
||||
return event;
|
||||
}
|
||||
|
||||
void _termEventDelete(PKVM* vm, void* event) {
|
||||
pkRealloc(vm, event, 0);
|
||||
}
|
||||
|
||||
void _termEventGetter(PKVM* vm) {
|
||||
const char* name;
|
||||
if (!pkValidateSlotString(vm, 1, &name, NULL)) return;
|
||||
|
||||
term_Event* event = pkGetSelf(vm);
|
||||
|
||||
if (strcmp(name, "type") == 0) {
|
||||
pkSetSlotNumber(vm, 0, (double)event->type);
|
||||
|
||||
} else if (strcmp(name, "keycode") == 0) {
|
||||
pkSetSlotNumber(vm, 0, (double)event->key.code);
|
||||
|
||||
} else if (strcmp(name, "ascii") == 0) {
|
||||
pkSetSlotNumber(vm, 0, (double)event->key.ascii);
|
||||
|
||||
} else if (strcmp(name, "modifiers") == 0) {
|
||||
if (event->type == TERM_ET_KEY_DOWN) {
|
||||
pkSetSlotNumber(vm, 0, (double)event->key.modifiers);
|
||||
} else {
|
||||
pkSetSlotNumber(vm, 0, (double)event->mouse.modifiers);
|
||||
}
|
||||
|
||||
} else if (strcmp(name, "button") == 0) {
|
||||
pkSetSlotNumber(vm, 0, (double)event->mouse.button);
|
||||
|
||||
} else if (strcmp(name, "pos") == 0) {
|
||||
pkReserveSlots(vm, 2);
|
||||
_setSlotVector(vm, 0, 1, event->mouse.pos.x, event->mouse.pos.y);
|
||||
|
||||
} else if (strcmp(name, "scroll") == 0) {
|
||||
pkSetSlotBool(vm, 0, event->mouse.scroll);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void _registerEnums(PKVM* vm, PkHandle* term) {
|
||||
pkReserveSlots(vm, 1);
|
||||
pkSetSlotHandle(vm, 0, term);
|
||||
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_UNKNOWN); pkSetAttribute(vm, 0, "KEY_UNKNOWN", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_0); pkSetAttribute(vm, 0, "KEY_0", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_1); pkSetAttribute(vm, 0, "KEY_1", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_2); pkSetAttribute(vm, 0, "KEY_2", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_3); pkSetAttribute(vm, 0, "KEY_3", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_4); pkSetAttribute(vm, 0, "KEY_4", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_5); pkSetAttribute(vm, 0, "KEY_5", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_6); pkSetAttribute(vm, 0, "KEY_6", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_7); pkSetAttribute(vm, 0, "KEY_7", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_8); pkSetAttribute(vm, 0, "KEY_8", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_9); pkSetAttribute(vm, 0, "KEY_9", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_A); pkSetAttribute(vm, 0, "KEY_A", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_B); pkSetAttribute(vm, 0, "KEY_B", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_C); pkSetAttribute(vm, 0, "KEY_C", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_D); pkSetAttribute(vm, 0, "KEY_D", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_E); pkSetAttribute(vm, 0, "KEY_E", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F); pkSetAttribute(vm, 0, "KEY_F", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_G); pkSetAttribute(vm, 0, "KEY_G", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_H); pkSetAttribute(vm, 0, "KEY_H", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_I); pkSetAttribute(vm, 0, "KEY_I", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_J); pkSetAttribute(vm, 0, "KEY_J", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_K); pkSetAttribute(vm, 0, "KEY_K", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_L); pkSetAttribute(vm, 0, "KEY_L", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_M); pkSetAttribute(vm, 0, "KEY_M", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_N); pkSetAttribute(vm, 0, "KEY_N", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_O); pkSetAttribute(vm, 0, "KEY_O", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_P); pkSetAttribute(vm, 0, "KEY_P", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_Q); pkSetAttribute(vm, 0, "KEY_Q", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_R); pkSetAttribute(vm, 0, "KEY_R", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_S); pkSetAttribute(vm, 0, "KEY_S", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_T); pkSetAttribute(vm, 0, "KEY_T", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_U); pkSetAttribute(vm, 0, "KEY_U", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_V); pkSetAttribute(vm, 0, "KEY_V", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_W); pkSetAttribute(vm, 0, "KEY_W", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_X); pkSetAttribute(vm, 0, "KEY_X", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_Y); pkSetAttribute(vm, 0, "KEY_Y", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_Z); pkSetAttribute(vm, 0, "KEY_Z", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_ESC); pkSetAttribute(vm, 0, "KEY_ESC", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_ENTER); pkSetAttribute(vm, 0, "KEY_ENTER", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_SPACE); pkSetAttribute(vm, 0, "KEY_SPACE", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_HOME); pkSetAttribute(vm, 0, "KEY_HOME", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_END); pkSetAttribute(vm, 0, "KEY_END", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_PAGEUP); pkSetAttribute(vm, 0, "KEY_PAGEUP", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_PAGEDOWN); pkSetAttribute(vm, 0, "KEY_PAGEDOWN", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_LEFT); pkSetAttribute(vm, 0, "KEY_LEFT", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_UP); pkSetAttribute(vm, 0, "KEY_UP", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_RIGHT); pkSetAttribute(vm, 0, "KEY_RIGHT", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_DOWN); pkSetAttribute(vm, 0, "KEY_DOWN", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_INSERT); pkSetAttribute(vm, 0, "KEY_INSERT", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_DELETE); pkSetAttribute(vm, 0, "KEY_DELETE", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_BACKSPACE); pkSetAttribute(vm, 0, "KEY_BACKSPACE", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_TAB); pkSetAttribute(vm, 0, "KEY_TAB", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F1); pkSetAttribute(vm, 0, "KEY_F1", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F2); pkSetAttribute(vm, 0, "KEY_F2", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F3); pkSetAttribute(vm, 0, "KEY_F3", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F4); pkSetAttribute(vm, 0, "KEY_F4", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F5); pkSetAttribute(vm, 0, "KEY_F5", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F6); pkSetAttribute(vm, 0, "KEY_F6", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F7); pkSetAttribute(vm, 0, "KEY_F7", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F8); pkSetAttribute(vm, 0, "KEY_F8", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F9); pkSetAttribute(vm, 0, "KEY_F9", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F10); pkSetAttribute(vm, 0, "KEY_F10", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F11); pkSetAttribute(vm, 0, "KEY_F11", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_KEY_F12); pkSetAttribute(vm, 0, "KEY_F12", 1);
|
||||
|
||||
pkSetSlotNumber(vm, 1, TERM_MB_UNKNOWN); pkSetAttribute(vm, 0, "BUTTON_UNKNOWN", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_MB_LEFT); pkSetAttribute(vm, 0, "BUTTON_LEFT", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_MB_MIDDLE); pkSetAttribute(vm, 0, "BUTTON_MIDDLE", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_MB_RIGHT); pkSetAttribute(vm, 0, "BUTTON_RIGHT", 1);
|
||||
|
||||
pkSetSlotNumber(vm, 1, TERM_MD_NONE); pkSetAttribute(vm, 0, "MD_NONE", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_MD_CTRL); pkSetAttribute(vm, 0, "MD_CTRL", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_MD_ALT); pkSetAttribute(vm, 0, "MD_ALT", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_MD_SHIFT); pkSetAttribute(vm, 0, "MD_SHIFT", 1);
|
||||
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_UNKNOWN); pkSetAttribute(vm, 0, "EVENT_UNKNOWN", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_KEY_DOWN); pkSetAttribute(vm, 0, "EVENT_KEY_DOWN", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_RESIZE); pkSetAttribute(vm, 0, "EVENT_RESIZE", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_DOUBLE_CLICK); pkSetAttribute(vm, 0, "EVENT_DOUBLE_CLICK", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_MOUSE_DOWN); pkSetAttribute(vm, 0, "EVENT_MOUSE_DOWN", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_MOUSE_UP); pkSetAttribute(vm, 0, "EVENT_MOUSE_UP", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_MOUSE_MOVE); pkSetAttribute(vm, 0, "EVENT_MOUSE_MOVE", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_MOUSE_DRAG); pkSetAttribute(vm, 0, "EVENT_MOUSE_DRAG", 1);
|
||||
pkSetSlotNumber(vm, 1, TERM_ET_MOUSE_SCROLL); pkSetAttribute(vm, 0, "EVENT_MOUSE_SCROLL", 1);
|
||||
|
||||
}
|
||||
|
||||
void _termInit(PKVM* vm) {
|
||||
bool capture_events;
|
||||
if (!pkValidateSlotBool(vm, 1, &capture_events)) return;
|
||||
term_init(capture_events);
|
||||
}
|
||||
|
||||
void _termCleanup(PKVM* vm) {
|
||||
term_cleanup();
|
||||
}
|
||||
|
||||
void _termIsatty(PKVM* vm) {
|
||||
pkSetSlotBool(vm, 0, term_isatty());
|
||||
}
|
||||
|
||||
void _termNewScreenBuffer(PKVM* vm) {
|
||||
term_new_screen_buffer();
|
||||
}
|
||||
|
||||
void _termRestoreScreenBuffer(PKVM* vm) {
|
||||
term_restore_screen_buffer();
|
||||
}
|
||||
|
||||
void _termGetSize(PKVM* vm) {
|
||||
pkReserveSlots(vm, 2);
|
||||
term_Vec size = term_getsize();
|
||||
_setSlotVector(vm, 0, 1, size.x, size.y);
|
||||
}
|
||||
|
||||
void _termGetPosition(PKVM* vm) {
|
||||
pkReserveSlots(vm, 2);
|
||||
term_Vec pos = term_getposition();
|
||||
_setSlotVector(vm, 0, 1, pos.x, pos.y);
|
||||
}
|
||||
|
||||
void _termSetPosition(PKVM* vm) {
|
||||
double x, y;
|
||||
|
||||
int argc = pkGetArgc(vm);
|
||||
if (!pkCheckArgcRange(vm, argc, 1, 2)) return;
|
||||
|
||||
if (argc == 1) {
|
||||
pkReserveSlots(vm, 3);
|
||||
if (!pkGetAttribute(vm, 1, "x", 2)) return;
|
||||
if (!pkValidateSlotNumber(vm, 2, &x)) return;
|
||||
|
||||
if (!pkGetAttribute(vm, 1, "y", 2)) return;
|
||||
if (!pkValidateSlotNumber(vm, 2, &y)) return;
|
||||
} else {
|
||||
if (!pkValidateSlotNumber(vm, 1, &x)) return;
|
||||
if (!pkValidateSlotNumber(vm, 2, &y)) return;
|
||||
}
|
||||
|
||||
term_Vec pos = term_vec((int)x, (int)y);
|
||||
term_setposition(pos);
|
||||
}
|
||||
|
||||
void _termReadEvent(PKVM* vm) {
|
||||
pkReserveSlots(vm, 3);
|
||||
pkSetSlotHandle(vm, 2, _cls_term_event);
|
||||
if (!pkValidateSlotInstanceOf(vm, 1, 2)) return;
|
||||
|
||||
term_Event* event = pkGetSlotNativeInstance(vm, 1);
|
||||
pkSetSlotBool(vm, 0, term_read_event(event));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MODULE REGISTER */
|
||||
/*****************************************************************************/
|
||||
|
||||
void registerModuleTerm(PKVM* vm) {
|
||||
PkHandle* term = pkNewModule(vm, "term");
|
||||
|
||||
_registerEnums(vm, term);
|
||||
pkModuleAddFunction(vm, term, "init", _termInit, 1);
|
||||
pkModuleAddFunction(vm, term, "cleanup", _termCleanup, 0);
|
||||
pkModuleAddFunction(vm, term, "isatty", _termIsatty, 0);
|
||||
pkModuleAddFunction(vm, term, "new_screen_buffer", _termNewScreenBuffer, 0);
|
||||
pkModuleAddFunction(vm, term, "restore_screen_buffer", _termRestoreScreenBuffer, 0);
|
||||
pkModuleAddFunction(vm, term, "getsize", _termGetSize, 0);
|
||||
pkModuleAddFunction(vm, term, "getposition", _termGetPosition, 0);
|
||||
pkModuleAddFunction(vm, term, "setposition", _termSetPosition, -1);
|
||||
pkModuleAddFunction(vm, term, "read_event", _termReadEvent, 1);
|
||||
|
||||
_cls_term_event = pkNewClass(vm, "Event", NULL, term, _termEventNew, _termEventDelete);
|
||||
pkClassAddMethod(vm, _cls_term_event, "@getter", _termEventGetter, 1);
|
||||
|
||||
pkRegisterModule(vm, term);
|
||||
pkReleaseHandle(vm, term);
|
||||
}
|
||||
|
||||
void cleanupModuleTerm(PKVM* vm) {
|
||||
if (_cls_term_event) pkReleaseHandle(vm, _cls_term_event);
|
||||
}
|
||||
|
@ -17,6 +17,9 @@ void registerModuleIO(PKVM* vm);
|
||||
void registerModulePath(PKVM* vm);
|
||||
void registerModuleDummy(PKVM* vm);
|
||||
|
||||
void registerModuleTerm(PKVM* vm);
|
||||
void cleanupModuleTerm(PKVM* vm);
|
||||
|
||||
// Registers the modules.
|
||||
void registerLibs(PKVM* vm) {
|
||||
registerModuleMath(vm);
|
||||
@ -25,8 +28,11 @@ void registerLibs(PKVM* vm) {
|
||||
registerModuleIO(vm);
|
||||
registerModulePath(vm);
|
||||
registerModuleDummy(vm);
|
||||
|
||||
registerModuleTerm(vm);
|
||||
}
|
||||
|
||||
// Cleanup the modules.
|
||||
void cleanupLibs(PKVM* vm) {
|
||||
cleanupModuleTerm(vm);
|
||||
}
|
||||
|
21
src/libs/thirdparty/term/LICENSE
vendored
Normal file
21
src/libs/thirdparty/term/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Thakee Nathees
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
1012
src/libs/thirdparty/term/term.h
vendored
Normal file
1012
src/libs/thirdparty/term/term.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
124
tests/examples/snake.pk
Normal file
124
tests/examples/snake.pk
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
import tui, term, math
|
||||
from types import Vector
|
||||
|
||||
## This is a pocketlang implementation of:
|
||||
## https://www.youtube.com/watch?v=xGmXxpIj6vs&t=279s&ab_channel=ChrisDeLeonofHomeTeamGameDev
|
||||
|
||||
## x, y velocity of snake.
|
||||
vx = 0; vy = 0
|
||||
|
||||
## position (at the middle).
|
||||
px = 0; py = 0
|
||||
|
||||
## tile size.
|
||||
tx = 0; ty = 0
|
||||
|
||||
## apple position.
|
||||
ax = 15; ay = 15
|
||||
|
||||
## tail, trail
|
||||
trail = []
|
||||
tail = 15
|
||||
|
||||
## score
|
||||
score = 0
|
||||
|
||||
def init()
|
||||
size = tui.get_size()
|
||||
tx = size.x
|
||||
ty = size.y
|
||||
|
||||
px = tx / 2; py = ty / 2
|
||||
end
|
||||
|
||||
def frame()
|
||||
px += vx
|
||||
py += vy
|
||||
if px < 0 then px = tx - 1 end
|
||||
if px > tx - 1 then px = 0 end
|
||||
if py < 0 then py = ty - 1 end
|
||||
if py > ty - 1 then py = 0 end
|
||||
|
||||
tui.clear()
|
||||
tui.string('press Q to quit | score = $score')
|
||||
|
||||
for i in trail
|
||||
tui.set_position(i.x, i.y)
|
||||
tui.start_bg(0, 0xff, 0)
|
||||
tui.string(' ')
|
||||
tui.end_bg()
|
||||
|
||||
if i.x == px and i.y == py
|
||||
tail = 5
|
||||
end
|
||||
end
|
||||
|
||||
tui.set_position(ax, ay)
|
||||
tui.start_bg(0xff, 0, 0)
|
||||
tui.string(' ')
|
||||
tui.end_bg()
|
||||
|
||||
trail.append(Vector(px, py))
|
||||
while trail.length > tail
|
||||
trail.pop(0)
|
||||
end
|
||||
|
||||
if px == ax and py == ay
|
||||
tail += 1
|
||||
score += 1
|
||||
ax = math.rand() % tx
|
||||
ay = math.rand() % ty
|
||||
end
|
||||
tui.flush()
|
||||
end
|
||||
|
||||
def handle(event)
|
||||
if event.type == term.EVENT_KEY_DOWN
|
||||
if event.keycode == term.KEY_Q
|
||||
tui.stop()
|
||||
end
|
||||
|
||||
## The "Switch Statement" alternative.
|
||||
{
|
||||
term.KEY_LEFT: fn
|
||||
vx = -1; vy = 0
|
||||
end,
|
||||
|
||||
term.KEY_UP: fn
|
||||
vx = 0; vy = -1
|
||||
end,
|
||||
|
||||
term.KEY_DOWN: fn
|
||||
vx = 0; vy = 1
|
||||
end,
|
||||
|
||||
term.KEY_RIGHT: fn
|
||||
vx = 1; vy = 0
|
||||
end,
|
||||
|
||||
term.KEY_T: fn
|
||||
math.sin(12)
|
||||
end,
|
||||
|
||||
}.get(event.keycode, fn end)()
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def main()
|
||||
config = tui.Config()
|
||||
config.capture_events = true
|
||||
config.hide_cursor = true
|
||||
config.new_buffer = true
|
||||
config.fps = 20
|
||||
config.init_fn = init
|
||||
config.event_fn = handle
|
||||
config.frame_fn = frame
|
||||
tui.run(config)
|
||||
end
|
||||
|
||||
|
||||
main()
|
||||
|
321
tests/examples/tui/_init.pk
Normal file
321
tests/examples/tui/_init.pk
Normal file
@ -0,0 +1,321 @@
|
||||
|
||||
import term, io
|
||||
from time import clock, sleep
|
||||
from types import ByteBuffer
|
||||
|
||||
def write(msg)
|
||||
io.write(io.stdout, msg)
|
||||
end
|
||||
|
||||
## The configuration that should be used to create tui context
|
||||
## and run.
|
||||
class Config
|
||||
def _init()
|
||||
self.title = null
|
||||
self.fps = 60
|
||||
self.hide_cursor = false
|
||||
self.capture_events = false
|
||||
self.new_buffer = false
|
||||
|
||||
self.init_fn = null
|
||||
self.event_fn = null
|
||||
self.frame_fn = null
|
||||
self.cleanup_fn = null
|
||||
end
|
||||
end
|
||||
|
||||
## Interlan context contains draw buffer and other data.
|
||||
class _Context
|
||||
def _init()
|
||||
self.buff = ByteBuffer()
|
||||
self.clear()
|
||||
end
|
||||
|
||||
## Called to reset all the internal for reusing the context.
|
||||
def clear()
|
||||
self.buff.clear()
|
||||
self.done = false ## If true the main loop ends.
|
||||
end
|
||||
end
|
||||
|
||||
## Internal global context.
|
||||
_ctx = _Context()
|
||||
|
||||
## -------------------------------------------------------------------------
|
||||
## FUNCTIONS
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
## Flush all the buffered bytes in the context's buffer.
|
||||
def flush()
|
||||
write(_ctx.buff.string())
|
||||
io.flush()
|
||||
_ctx.buff.clear()
|
||||
end
|
||||
|
||||
## Stops the main loop and return from run().
|
||||
def stop()
|
||||
_ctx.done = true
|
||||
end
|
||||
|
||||
def set_title(title)
|
||||
write("\x1b]0;$title\x07")
|
||||
end
|
||||
|
||||
def hide_cursor()
|
||||
write("\x1b[?25l")
|
||||
end
|
||||
|
||||
def show_cursor()
|
||||
write("\x1b[?25h")
|
||||
end
|
||||
|
||||
## It'll write escape sequence to move the cursor but not actually move.
|
||||
## for this to make effect, one should flush the buffer.
|
||||
def set_position(x, y)
|
||||
_ctx.buff.write("\x1b[${y + 1};${x + 1}H")
|
||||
end
|
||||
|
||||
def get_size()
|
||||
return term.getsize()
|
||||
end
|
||||
|
||||
##
|
||||
## Hex ASCII DEC-Line-Drawing
|
||||
## ------------------------------
|
||||
## 0x6a j ┘
|
||||
## 0x6b k ┐
|
||||
## 0x6c l ┌
|
||||
## 0x6d m └
|
||||
## 0x6e n ┼
|
||||
## 0x71 q ─
|
||||
## 0x74 t ├
|
||||
## 0x75 u ┤
|
||||
## 0x76 v ┴
|
||||
## 0x77 w ┬
|
||||
## 0x78 x │
|
||||
##
|
||||
def box_char(c)
|
||||
_ctx.buff.write("\x1b(0$c\x1b(B")
|
||||
end
|
||||
|
||||
## FIXME: Implement str * int multiplicatin to support
|
||||
##
|
||||
## "\x1b(0${ c * n }\x1b(B"
|
||||
##
|
||||
## and define box_char_len() or refactor the above to take argument n.
|
||||
|
||||
## Write a string to the context buffer.
|
||||
def string(s)
|
||||
_ctx.buff.write(str(s))
|
||||
end
|
||||
|
||||
## Clear the screen and move cursor to (0, 0).
|
||||
def clear()
|
||||
_ctx.buff.write("\x1b[H\x1b[J")
|
||||
end
|
||||
|
||||
## Clear everythin from cursor to EOL.
|
||||
def clear_eol()
|
||||
_ctx.buff.write("\x1b[K")
|
||||
end
|
||||
|
||||
## Clear everythin from cursor to EOF.
|
||||
def clear_eof()
|
||||
_ctx.buff.write("\x1b[J")
|
||||
end
|
||||
|
||||
## Reset all the stylings.
|
||||
def reset()
|
||||
_ctx.buff.write("\x1b[0m")
|
||||
end
|
||||
|
||||
def _is_valid_color(r, g, b)
|
||||
return r is Number and g is Number and b is Number
|
||||
return r.isbyte() and g.isbyte() and b.isbyte()
|
||||
end
|
||||
|
||||
## Set the forground color.
|
||||
def start_color(r, g, b)
|
||||
assert(_is_valid_color(r, g, b))
|
||||
_ctx.buff.write("\x1b[38;2;$r;$g;${b}m")
|
||||
end
|
||||
|
||||
## End the forground color.
|
||||
def end_color()
|
||||
_ctx.buff.write("\x1b[39m")
|
||||
end
|
||||
|
||||
## Start the background color.
|
||||
def start_bg(r, g, b)
|
||||
assert(_is_valid_color(r, g, b))
|
||||
_ctx.buff.write("\x1b[48;2;$r;$g;${b}m")
|
||||
end
|
||||
|
||||
## End the background color.
|
||||
def end_bg()
|
||||
_ctx.buff.write("\x1b[49m")
|
||||
end
|
||||
|
||||
def start_bold()
|
||||
_ctx.buff.write("\x1b[1m")
|
||||
end
|
||||
|
||||
def end_bold()
|
||||
_ctx.buff.write("\x1b[22m")
|
||||
end
|
||||
|
||||
def start_dim()
|
||||
_ctx.buff.write("\x1b[2m")
|
||||
end
|
||||
|
||||
def end_dim()
|
||||
_ctx.buff.write("\x1b[22m")
|
||||
end
|
||||
|
||||
def start_italic()
|
||||
_ctx.buff.write("\x1b[3m")
|
||||
end
|
||||
|
||||
def end_italic()
|
||||
_ctx.buff.write("\x1b[23m")
|
||||
end
|
||||
|
||||
def start_underline()
|
||||
_ctx.buff.write("\x1b[4m")
|
||||
end
|
||||
|
||||
def end_underline()
|
||||
_ctx.buff.write("\x1b[24m")
|
||||
end
|
||||
|
||||
def start_hidden()
|
||||
_ctx.buff.write("\x1b[8m")
|
||||
end
|
||||
|
||||
def end_hidden()
|
||||
_ctx.buff.write("\x1b[28m")
|
||||
end
|
||||
|
||||
def start_strikethrough()
|
||||
_ctx.buff.write("\x1b[9m")
|
||||
end
|
||||
|
||||
def end_strikethrough()
|
||||
_ctx.buff.write("\x1b[29m")
|
||||
end
|
||||
|
||||
def start_color_black()
|
||||
_ctx.buff.write("\x1b[30m")
|
||||
end
|
||||
|
||||
def end_color_black()
|
||||
_ctx.buff.write("\x1b[40m")
|
||||
end
|
||||
|
||||
def start_color_red()
|
||||
_ctx.buff.write("\x1b[31m")
|
||||
end
|
||||
|
||||
def end_color_red()
|
||||
_ctx.buff.write("\x1b[41m")
|
||||
end
|
||||
|
||||
def start_color_green()
|
||||
_ctx.buff.write("\x1b[32m")
|
||||
end
|
||||
|
||||
def end_color_green()
|
||||
_ctx.buff.write("\x1b[42m")
|
||||
end
|
||||
|
||||
def start_color_yellow()
|
||||
_ctx.buff.write("\x1b[33m")
|
||||
end
|
||||
|
||||
def end_color_yellow()
|
||||
_ctx.buff.write("\x1b[43m")
|
||||
end
|
||||
|
||||
def start_color_blue()
|
||||
_ctx.buff.write("\x1b[34m")
|
||||
end
|
||||
|
||||
def end_color_blue()
|
||||
_ctx.buff.write("\x1b[44m")
|
||||
end
|
||||
|
||||
def start_color_magenta()
|
||||
_ctx.buff.write("\x1b[35m")
|
||||
end
|
||||
|
||||
def end_color_magenta()
|
||||
_ctx.buff.write("\x1b[45m")
|
||||
end
|
||||
|
||||
def start_color_cyan()
|
||||
_ctx.buff.write("\x1b[36m")
|
||||
end
|
||||
|
||||
def end_color_cyan()
|
||||
_ctx.buff.write("\x1b[46m")
|
||||
end
|
||||
|
||||
def start_color_white()
|
||||
_ctx.buff.write("\x1b[37m")
|
||||
end
|
||||
|
||||
def end_color_white()
|
||||
_ctx.buff.write("\x1b[47m")
|
||||
end
|
||||
|
||||
def start_color_default()
|
||||
_ctx.buff.write("\x1b[39m")
|
||||
end
|
||||
|
||||
def end_color_default()
|
||||
_ctx.buff.write("\x1b[49m")
|
||||
end
|
||||
|
||||
|
||||
## -------------------------------------------------------------------------
|
||||
## TUI MAIN LOOP
|
||||
## -------------------------------------------------------------------------
|
||||
|
||||
def run(config)
|
||||
term.init(config.capture_events)
|
||||
|
||||
if config.new_buffer then term.new_screen_buffer() end
|
||||
if config.hide_cursor then hide_cursor() end
|
||||
if config.init_fn then config.init_fn() end
|
||||
|
||||
event = term.Event()
|
||||
|
||||
## The main loop.
|
||||
while not _ctx.done
|
||||
start = clock()
|
||||
|
||||
## Dispatch events.
|
||||
while term.read_event(event)
|
||||
if config.event_fn then config.event_fn(event) end
|
||||
if _ctx.done then break end
|
||||
end
|
||||
|
||||
## Run frame function
|
||||
if config.frame_fn then config.frame_fn() end
|
||||
|
||||
## Sleep to sync FPS.
|
||||
et = clock() - start ## Elapsed time.
|
||||
ft = 1 / config.fps ## Frame time.
|
||||
|
||||
## TODO: set title to print fps if said in config.
|
||||
if ft > et then sleep((ft - et) * 1000) end
|
||||
end
|
||||
|
||||
## Cleanup.
|
||||
if config.cleanup_fn then config.cleanup_fn() end
|
||||
if config.hide_cursor then show_cursor() end
|
||||
if config.new_buffer then term.restore_screen_buffer() end
|
||||
term.cleanup()
|
||||
_ctx.clear()
|
||||
|
||||
end
|
@ -72,6 +72,7 @@ assert(val == 'bar')
|
||||
|
||||
|
||||
def test_in_local()
|
||||
x = false
|
||||
if x = fn y = false; return not y end ()
|
||||
assert(x == true)
|
||||
end
|
||||
|
@ -16,6 +16,7 @@ def read_file()
|
||||
'line4 : qux\n',
|
||||
]
|
||||
|
||||
line = ''
|
||||
while line = f.getline()
|
||||
assert(line in LINES)
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user