Port of Micro Python to NuttX. From Dave Marples
This commit is contained in:
parent
632480ce24
commit
63b265b640
@ -38,10 +38,14 @@ ifeq ($(CONFIG_INTERPRETERS_BAS),y)
|
||||
CONFIGURED_APPS += interpreters/bas
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_PCODE),y)
|
||||
CONFIGURED_APPS += interpreters/pcode
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_FICL),y)
|
||||
CONFIGURED_APPS += interpreters/ficl
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_MICROPYTHON),y)
|
||||
CONFIGURED_APPS += interpreters/micropython
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_PCODE),y)
|
||||
CONFIGURED_APPS += interpreters/pcode
|
||||
endif
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
# Sub-directories containing interpreter runtime
|
||||
|
||||
SUBDIRS = pcode prun ficl bas
|
||||
SUBDIRS = bas ficl micropython pcode prun
|
||||
|
||||
# Create the list of installed runtime modules (INSTALLED_DIRS)
|
||||
|
||||
|
@ -12,6 +12,25 @@ ficl
|
||||
is not in that directory, only an environment and instructions that will
|
||||
let you build Ficl under NuttX. The rest is up to you.
|
||||
|
||||
micropython
|
||||
-----------
|
||||
|
||||
This is a port of a build environment for Micro Python:
|
||||
|
||||
https://micropython.org/
|
||||
|
||||
NOTE that Micro Python is not included in this directory. Before building
|
||||
this example, you must first download Micro Python from:
|
||||
|
||||
https://micropython.org/download/
|
||||
|
||||
Or clone from the GIT repository:
|
||||
|
||||
https://github.com/micropython/
|
||||
|
||||
This port was contributed by Dave Marples using Micro Python circu
|
||||
1.3.8. It may not be compatible with other versions.
|
||||
|
||||
pcode
|
||||
-----
|
||||
|
||||
|
11
interpreters/micropython/.gitignore
vendored
Normal file
11
interpreters/micropython/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/Make.dep
|
||||
/.depend
|
||||
/.built
|
||||
/*.asm
|
||||
/*.obj
|
||||
/*.rel
|
||||
/*.lst
|
||||
/*.sym
|
||||
/*.adb
|
||||
/*.lib
|
||||
/*.src
|
34
interpreters/micropython/Kconfig
Normal file
34
interpreters/micropython/Kconfig
Normal file
@ -0,0 +1,34 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see misc/tools/kconfig-language.txt.
|
||||
#
|
||||
|
||||
config INTERPRETERS_MICROPYTHON
|
||||
bool "Micro Python support"
|
||||
default n
|
||||
---help---
|
||||
Enable support for the Micro Python interpreter
|
||||
|
||||
if INTERPRETERS_MICROPYTHON
|
||||
|
||||
config INTERPRETERS_MICROPYTHON_APPNAME
|
||||
string "Executable name"
|
||||
default "micropython"
|
||||
depends on NSH_BUILTIN_APPS
|
||||
|
||||
config INTERPRETERS_MICROPYTHON_STACKSIZE
|
||||
int "Interpreter stack size"
|
||||
default 2048
|
||||
depends on NSH_BUILTIN_APPS
|
||||
|
||||
config INTERPRETERS_MICROPYTHON_PRIORITY
|
||||
int "Interpreter priority"
|
||||
default 100
|
||||
depends on NSH_BUILTIN_APPS
|
||||
|
||||
CONFIG_INTERPRETERS_MICROPYTHON_PROGNAME
|
||||
string "Program name"
|
||||
default "micropython"
|
||||
depends on BUILD_KERNEL
|
||||
|
||||
endif # INTERPRETERS_MICROPYTHON
|
143
interpreters/micropython/Makefile
Normal file
143
interpreters/micropython/Makefile
Normal file
@ -0,0 +1,143 @@
|
||||
############################################################################
|
||||
# apps/ interpreters/micropython/Makefile
|
||||
#
|
||||
# Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
# Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
# Dave Marples <dave@marples.net>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
TOP ?= ../../../../micropython
|
||||
TOPDIR ?= ../../../nuttx
|
||||
APPDIR ?= ../../../apps
|
||||
|
||||
MICROPYTHON_DIR = $(TOP)/py
|
||||
|
||||
include $(MICROPYTHON_DIR)/mkenv.mk
|
||||
|
||||
# qstr definitions (must come before including py.mk)
|
||||
|
||||
QSTR_DEFS = qstrdefsport.h
|
||||
|
||||
# include py core make definitions
|
||||
|
||||
include $(MICROPYTHON_DIR)/py.mk
|
||||
|
||||
-include $(TOPDIR)/.config
|
||||
-include $(TOPDIR)/Make.defs
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
# c99 is needed for micropython
|
||||
|
||||
CFLAGS+=-std=c99 -Wno-shadow -Wno-strict-prototypes
|
||||
|
||||
INC = -I. -I$(TOP) -I$(PY_SRC) -I$(BUILD)
|
||||
|
||||
CFLAGS +=$(INC)
|
||||
|
||||
CONFIG_INTERPRETERS_MICROPYTHON_APPNAME ?= micropython
|
||||
CONFIG_INTERPRETERS_MICROPYTHON_STACKSIZE ?= 2048
|
||||
CONFIG_INTERPRETERS_MICROPYTHON_PRIORITY ?= SCHED_PRIORITY_DEFAULT
|
||||
|
||||
APPNAME = $(CONFIG_INTERPRETERS_MICROPYTHON_APPNAME)
|
||||
STACKSIZE = $(CONFIG_INTERPRETERS_MICROPYTHON_STACKSIZE)
|
||||
PRIORITY = $(CONFIG_INTERPRETERS_MICROPYTHON_PRIORITY)
|
||||
|
||||
CONFIG_INTERPRETERS_MICROPYTHON_PROGNAME ?= micropython$(EXEEXT)
|
||||
PROGNAME = $(CONFIG_INTERPRETERS_MICROPYTHON_PROGNAME)
|
||||
|
||||
ASRCS =
|
||||
CSRCS = pyexec.c py_readline.c
|
||||
MAINSRC = micropython_main.c
|
||||
|
||||
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(ASRC:.S=$(OBJEXT)) $(CSRCS:.c=$(OBJEXT)))
|
||||
|
||||
ifneq ($(CONFIG_BUILD_KERNEL),y)
|
||||
OBJ += $(addprefix $(BUILD)/, $(MAINSRC:.c=$(OBJEXT)))
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
|
||||
BIN = ..\..\libapps$(LIBEXT)
|
||||
else
|
||||
ifeq ($(WINTOOL),y)
|
||||
BIN = ..\\..\\libapps$(LIBEXT)
|
||||
else
|
||||
BIN = ../../libapps$(LIBEXT)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(WINTOOL),y)
|
||||
INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}"
|
||||
else
|
||||
INSTALL_DIR = $(BIN_DIR)
|
||||
endif
|
||||
|
||||
ROOTDEPPATH = --dep-path .
|
||||
|
||||
# Common build
|
||||
|
||||
all: .built
|
||||
|
||||
.built: $(OBJ)
|
||||
$(call ARCHIVE, $(BIN), $(OBJ))
|
||||
@touch .built
|
||||
|
||||
ifeq ($(CONFIG_BUILD_KERNEL),y)
|
||||
$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJ) $(MAINOBJ)
|
||||
@echo "LD: $(PROGNAME)"
|
||||
$(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS)
|
||||
$(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME)
|
||||
|
||||
install: $(BIN_DIR)$(DELIM)$(PROGNAME)
|
||||
else
|
||||
install:
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
|
||||
$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
|
||||
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),micropython_main)
|
||||
|
||||
context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
|
||||
else
|
||||
context:
|
||||
endif
|
||||
|
||||
.depend: Makefile $(SRCS)
|
||||
@$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
|
||||
@touch $@
|
||||
|
||||
depend: .depend
|
||||
|
||||
distclean: clean
|
||||
$(call DELFILE, Make.dep)
|
||||
$(call DELFILE, .depend)
|
||||
|
||||
include $(MICROPYTHON_DIR)/mkrules.mk
|
||||
-include Make.dep
|
263
interpreters/micropython/micropython_main.c
Normal file
263
interpreters/micropython/micropython_main.c
Normal file
@ -0,0 +1,263 @@
|
||||
/****************************************************************************
|
||||
* interpreters/micropython/micropython_main.c
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
* Dave Marples <dave@marples.net>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
#include "obj.h"
|
||||
#include "parsehelper.h"
|
||||
#include "compile.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "repl.h"
|
||||
#include "pfenv.h"
|
||||
#include "pyexec.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define FORCE_EVAL(x) do { \
|
||||
if (sizeof(x) == sizeof(float)) { \
|
||||
volatile float __x; \
|
||||
__x = (x); \
|
||||
(void)__x; \
|
||||
} else if (sizeof(x) == sizeof(double)) { \
|
||||
volatile double __x; \
|
||||
__x = (x); \
|
||||
(void)__x; \
|
||||
} else { \
|
||||
volatile long double __x; \
|
||||
__x = (x); \
|
||||
(void)__x; \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function
|
||||
****************************************************************************/
|
||||
|
||||
void do_str(FAR const char *src)
|
||||
{
|
||||
FAR mp_lexer_t *lex =
|
||||
mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
|
||||
if (lex == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mp_parse_error_kind_t parse_error_kind;
|
||||
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind);
|
||||
|
||||
if (pn == MP_PARSE_NODE_NULL)
|
||||
{
|
||||
/* parse error */
|
||||
|
||||
mp_parse_show_exception(lex, parse_error_kind);
|
||||
mp_lexer_free(lex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* parse okay */
|
||||
|
||||
qstr source_name = lex->source_name;
|
||||
mp_lexer_free(lex);
|
||||
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);
|
||||
|
||||
if (mp_obj_is_exception_instance(module_fun))
|
||||
{
|
||||
/* compile error */
|
||||
|
||||
mp_obj_print_exception(printf_wrapper, NULL, module_fun);
|
||||
return;
|
||||
}
|
||||
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0)
|
||||
{
|
||||
mp_call_function_0(module_fun);
|
||||
nlr_pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* uncaught exception */
|
||||
|
||||
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t) nlr.ret_val);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
float nanf(FAR const char *tagp)
|
||||
{
|
||||
(void)tagp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
float copysignf(float x, float y)
|
||||
{
|
||||
if (y < 0)
|
||||
{
|
||||
return -fabsf(x);
|
||||
}
|
||||
|
||||
return fabsf(x);
|
||||
}
|
||||
|
||||
float truncf(float x)
|
||||
{
|
||||
union
|
||||
{
|
||||
float f;
|
||||
uint32_t i;
|
||||
} u =
|
||||
{
|
||||
x};
|
||||
int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9;
|
||||
uint32_t m;
|
||||
|
||||
if (e >= 23 + 9)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
if (e < 9)
|
||||
{
|
||||
e = 1;
|
||||
}
|
||||
|
||||
m = -1U >> e;
|
||||
if ((u.i & m) == 0)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
FORCE_EVAL(x + 0x1 p120f);
|
||||
u.i &= ~m;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* mp_import_stat
|
||||
****************************************************************************/
|
||||
|
||||
mp_import_stat_t mp_import_stat(FAR const char *path)
|
||||
{
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* mp_lexer_new_from_file
|
||||
****************************************************************************/
|
||||
|
||||
mp_lexer_t *mp_lexer_new_from_file(FAR const char *filename)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* mp_builtin_open
|
||||
****************************************************************************/
|
||||
|
||||
mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t * args, mp_map_t * kwargs)
|
||||
{
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
||||
|
||||
/****************************************************************************
|
||||
* nlr_jump_fail
|
||||
****************************************************************************/
|
||||
|
||||
void nlr_jump_fail(void *val)
|
||||
{
|
||||
fprintf(stderr, "FATAL: uncaught exception %p\n", val);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* micropython_main
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_INTERPRETERS_MICROPYTHON
|
||||
int micropython_main(int argc, char *argv[])
|
||||
{
|
||||
mp_init();
|
||||
for (;;)
|
||||
{
|
||||
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL)
|
||||
{
|
||||
if (pyexec_raw_repl() != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pyexec_friendly_repl() != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mp_deinit();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
117
interpreters/micropython/mpconfigport.h
Normal file
117
interpreters/micropython/mpconfigport.h
Normal file
@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
* interpreters/micropython/mpconfigport.h
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Authors: Dave Marples <dave@marples.net>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_INTERPRETERS_MICROPYTHON_MPCONFIGPORT_H
|
||||
#define __APPS_INTERPRETERS_MICROPYTHON_MPCONFIGPORT_H 1
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <wchar_t.h>
|
||||
|
||||
/* We need to provide a declaration/definition of alloca() */
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* options to control how Micro Python is built */
|
||||
|
||||
#define MICROPY_ALLOC_PATH_MAX (512)
|
||||
#define MICROPY_EMIT_X64 (0)
|
||||
#define MICROPY_EMIT_THUMB (0)
|
||||
#define MICROPY_EMIT_INLINE_THUMB (0)
|
||||
#define MICROPY_MEM_STATS (0)
|
||||
#define MICROPY_DEBUG_PRINTERS (0)
|
||||
#define MICROPY_ENABLE_GC (0)
|
||||
#define MICROPY_HELPER_REPL (1)
|
||||
#define MICROPY_HELPER_LEXER_UNIX (0)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (0)
|
||||
#define MICROPY_ENABLE_DOC_STRING (0)
|
||||
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
|
||||
#define MICROPY_PY_BUILTINS_FROZENSET (0)
|
||||
#define MICROPY_PY_BUILTINS_SET (0)
|
||||
#define MICROPY_PY_BUILTINS_SLICE (0)
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (0)
|
||||
#define MICROPY_PY___FILE__ (0)
|
||||
#define MICROPY_PY_GC (0)
|
||||
#define MICROPY_PY_ARRAY (0)
|
||||
#define MICROPY_PY_COLLECTIONS (0)
|
||||
#define MICROPY_PY_MATH (0)
|
||||
#define MICROPY_PY_CMATH (0)
|
||||
#define MICROPY_PY_IO (0)
|
||||
#define MICROPY_PY_STRUCT (0)
|
||||
#define MICROPY_PY_SYS (0)
|
||||
#define MICROPY_CPYTHON_COMPAT (0)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPL)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||
|
||||
/* type definitions for the specific machine */
|
||||
|
||||
#define BYTES_PER_WORD (4)
|
||||
|
||||
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
|
||||
|
||||
#define UINT_FMT "%lu"
|
||||
#define INT_FMT "%ld"
|
||||
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef int32_t mp_int_t; /* must be pointer size */
|
||||
typedef uint32_t mp_uint_t; /* must be pointer size */
|
||||
typedef void *machine_ptr_t; /* must be of pointer size */
|
||||
typedef const void *machine_const_ptr_t; /* must be of pointer size */
|
||||
typedef long mp_off_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* extra built in names to add to the global namespace */
|
||||
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
|
||||
|
||||
#endif /* __APPS_INTERPRETERS_MICROPYTHON_MPCONFIGPORT_H */
|
431
interpreters/micropython/py_readline.c
Normal file
431
interpreters/micropython/py_readline.c
Normal file
@ -0,0 +1,431 @@
|
||||
/****************************************************************************
|
||||
* interpreters/micropython/py_readline.c
|
||||
*
|
||||
* This file originated from the Micro Python project, http://micropython.org/
|
||||
* It has been hacked around to fit into Nuttx
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
* Further edits (c) 2015 Dave Marples
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/misc.h"
|
||||
#include "py_readline.h"
|
||||
|
||||
#if 0 /* print debugging info */
|
||||
# define DEBUG_PRINT (1)
|
||||
# define DEBUG_printf printf
|
||||
#else /* don't print debugging info */
|
||||
# define DEBUG_printf(...) (void)0
|
||||
#endif
|
||||
|
||||
#define READLINE_HIST_SIZE (8)
|
||||
|
||||
#define CURSOR_BACK ('\b')
|
||||
#define KEY_TAB ('\t')
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
ESEQ_NONE,
|
||||
ESEQ_ESC,
|
||||
ESEQ_ESC_BRACKET,
|
||||
ESEQ_ESC_BRACKET_DIGIT,
|
||||
ESEQ_ESC_O
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const char *readline_hist[READLINE_HIST_SIZE];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
STATIC char *str_dup_maybe(const char *str)
|
||||
{
|
||||
uint32_t len = strlen(str);
|
||||
char *s2 = m_new_maybe(char, len + 1);
|
||||
|
||||
if (s2 == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(s2, str, len + 1);
|
||||
return s2;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void readline_init0(void)
|
||||
{
|
||||
memset(readline_hist, 0, READLINE_HIST_SIZE * sizeof(const char *));
|
||||
}
|
||||
|
||||
int py_readline(vstr_t * line, const char *prompt)
|
||||
{
|
||||
fprintf(stdout, prompt);
|
||||
fflush(stdout);
|
||||
int orig_line_len = line->len;
|
||||
int escape_seq = ESEQ_NONE;
|
||||
char escape_seq_buf[1] = { 0 };
|
||||
int hist_cur = -1;
|
||||
int cursor_pos = orig_line_len;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int c = getc(stdin);
|
||||
int last_line_len = line->len;
|
||||
int redraw_step_back = 0;
|
||||
bool redraw_from_cursor = false;
|
||||
int redraw_step_forward = 0;
|
||||
if (escape_seq == ESEQ_NONE)
|
||||
{
|
||||
if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_D &&
|
||||
vstr_len(line) == orig_line_len)
|
||||
{
|
||||
/* control character with empty line */
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (c == CHAR_CTRL_A)
|
||||
{
|
||||
/* CTRL-A with non-empty line is go-to-start-of-line */
|
||||
|
||||
goto home_key;
|
||||
}
|
||||
else if (c == CHAR_CTRL_C)
|
||||
{
|
||||
/* CTRL-C with non-empty line is cancel */
|
||||
|
||||
return c;
|
||||
}
|
||||
else if (c == CHAR_CTRL_E)
|
||||
{
|
||||
/* CTRL-E is go-to-end-of-line */
|
||||
|
||||
goto end_key;
|
||||
}
|
||||
else if (c == '\r')
|
||||
{
|
||||
/* newline */
|
||||
|
||||
fputs("\r\n", stdout);
|
||||
if (line->len > orig_line_len &&
|
||||
(readline_hist[0] == NULL ||
|
||||
strcmp(readline_hist[0], line->buf + orig_line_len) != 0))
|
||||
{
|
||||
/* a line which is not empty and different from the last one
|
||||
* so update the history
|
||||
*/
|
||||
|
||||
char *most_recent_hist =
|
||||
str_dup_maybe(line->buf + orig_line_len);
|
||||
if (most_recent_hist != NULL)
|
||||
{
|
||||
for (int i = READLINE_HIST_SIZE - 1; i > 0; i--)
|
||||
{
|
||||
readline_hist[i] = readline_hist[i - 1];
|
||||
}
|
||||
|
||||
readline_hist[0] = most_recent_hist;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (c == 27)
|
||||
{
|
||||
/* escape sequence */
|
||||
|
||||
escape_seq = ESEQ_ESC;
|
||||
}
|
||||
else if (c == 8 || c == 127)
|
||||
{
|
||||
/* backspace/delete */
|
||||
|
||||
if (cursor_pos > orig_line_len)
|
||||
{
|
||||
vstr_cut_out_bytes(line, cursor_pos - 1, 1);
|
||||
|
||||
/* set redraw parameters */
|
||||
|
||||
redraw_step_back = 1;
|
||||
redraw_from_cursor = true;
|
||||
}
|
||||
}
|
||||
else if ((KEY_TAB == c) || (32 <= c && c <= 126))
|
||||
{
|
||||
/* printable character */
|
||||
|
||||
vstr_ins_char(line, cursor_pos, c);
|
||||
|
||||
/* set redraw parameters */
|
||||
|
||||
redraw_from_cursor = true;
|
||||
redraw_step_forward = 1;
|
||||
}
|
||||
}
|
||||
else if (escape_seq == ESEQ_ESC)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '[':
|
||||
escape_seq = ESEQ_ESC_BRACKET;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
escape_seq = ESEQ_ESC_O;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_printf("(ESC %d)", c);
|
||||
escape_seq = ESEQ_NONE;
|
||||
}
|
||||
}
|
||||
else if (escape_seq == ESEQ_ESC_BRACKET)
|
||||
{
|
||||
if ('0' <= c && c <= '9')
|
||||
{
|
||||
escape_seq = ESEQ_ESC_BRACKET_DIGIT;
|
||||
escape_seq_buf[0] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
escape_seq = ESEQ_NONE;
|
||||
if (c == 'A')
|
||||
{
|
||||
/* up arrow */
|
||||
|
||||
if (hist_cur + 1 < READLINE_HIST_SIZE &&
|
||||
readline_hist[hist_cur + 1] != NULL)
|
||||
{
|
||||
/* increase hist num */
|
||||
|
||||
hist_cur += 1;
|
||||
|
||||
/* set line to history */
|
||||
|
||||
line->len = orig_line_len;
|
||||
vstr_add_str(line, readline_hist[hist_cur]);
|
||||
|
||||
/* set redraw parameters */
|
||||
|
||||
redraw_step_back = cursor_pos - orig_line_len;
|
||||
redraw_from_cursor = true;
|
||||
redraw_step_forward = line->len - orig_line_len;
|
||||
}
|
||||
}
|
||||
else if (c == 'B')
|
||||
{
|
||||
/* down arrow */
|
||||
|
||||
if (hist_cur >= 0)
|
||||
{
|
||||
/* decrease hist num */
|
||||
|
||||
hist_cur -= 1;
|
||||
|
||||
/* set line to history */
|
||||
|
||||
vstr_cut_tail_bytes(line, line->len - orig_line_len);
|
||||
if (hist_cur >= 0)
|
||||
{
|
||||
vstr_add_str(line, readline_hist[hist_cur]);
|
||||
}
|
||||
|
||||
/* set redraw parameters */
|
||||
|
||||
redraw_step_back = cursor_pos - orig_line_len;
|
||||
redraw_from_cursor = true;
|
||||
redraw_step_forward = line->len - orig_line_len;
|
||||
}
|
||||
}
|
||||
else if (c == 'C')
|
||||
{
|
||||
/* right arrow */
|
||||
|
||||
if (cursor_pos < line->len)
|
||||
{
|
||||
redraw_step_forward = 1;
|
||||
}
|
||||
}
|
||||
else if (c == 'D')
|
||||
{
|
||||
/* left arrow */
|
||||
|
||||
if (cursor_pos > orig_line_len)
|
||||
{
|
||||
redraw_step_back = 1;
|
||||
}
|
||||
}
|
||||
else if (c == 'H')
|
||||
{
|
||||
/* home */
|
||||
|
||||
goto home_key;
|
||||
}
|
||||
else if (c == 'F')
|
||||
{
|
||||
/* end */
|
||||
|
||||
goto end_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_printf("(ESC [ %d)", c);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (escape_seq == ESEQ_ESC_BRACKET_DIGIT)
|
||||
{
|
||||
if (c == '~')
|
||||
{
|
||||
if (escape_seq_buf[0] == '1' || escape_seq_buf[0] == '7')
|
||||
{
|
||||
home_key:
|
||||
redraw_step_back = cursor_pos - orig_line_len;
|
||||
}
|
||||
else if (escape_seq_buf[0] == '4' || escape_seq_buf[0] == '8')
|
||||
{
|
||||
end_key:
|
||||
redraw_step_forward = line->len - cursor_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_printf("(ESC [ %c %d)", escape_seq_buf[0], c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_printf("(ESC [ %c %d)", escape_seq_buf[0], c);
|
||||
}
|
||||
|
||||
escape_seq = ESEQ_NONE;
|
||||
}
|
||||
else if (escape_seq == ESEQ_ESC_O)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'H':
|
||||
goto home_key;
|
||||
|
||||
case 'F':
|
||||
goto end_key;
|
||||
|
||||
default:
|
||||
DEBUG_printf("(ESC O %d)", c);
|
||||
escape_seq = ESEQ_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
escape_seq = ESEQ_NONE;
|
||||
}
|
||||
|
||||
/* redraw command prompt, efficiently
|
||||
* TODO we can probably use some more sophisticated VT100 commands here
|
||||
*/
|
||||
|
||||
if (redraw_step_back > 0)
|
||||
{
|
||||
for (int i = 0; i < redraw_step_back; i++)
|
||||
{
|
||||
fputc(CURSOR_BACK, stdout);
|
||||
}
|
||||
|
||||
cursor_pos -= redraw_step_back;
|
||||
}
|
||||
if (redraw_from_cursor)
|
||||
{
|
||||
if (line->len < last_line_len)
|
||||
{
|
||||
/* erase old chars */
|
||||
|
||||
for (int i = cursor_pos; i < last_line_len; i++)
|
||||
{
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
|
||||
/* step back */
|
||||
|
||||
for (int i = cursor_pos; i < last_line_len; i++)
|
||||
{
|
||||
fputc(CURSOR_BACK, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw new chars */
|
||||
|
||||
int charCount = 0;
|
||||
do
|
||||
{
|
||||
fputc(*(line->buf + cursor_pos + charCount), stdout);
|
||||
}
|
||||
while (charCount++ < (line->len - cursor_pos));
|
||||
|
||||
/* move cursor forward if needed (already moved forward by length of
|
||||
* line, so move it back)
|
||||
*/
|
||||
|
||||
for (int i = cursor_pos + redraw_step_forward; i < line->len; i++)
|
||||
{
|
||||
fputc(CURSOR_BACK, stdout);
|
||||
}
|
||||
|
||||
cursor_pos += redraw_step_forward;
|
||||
}
|
||||
else if (redraw_step_forward > 0)
|
||||
{
|
||||
/* draw over old chars to move cursor forwards */
|
||||
|
||||
int charCount = 0;
|
||||
do
|
||||
{
|
||||
fputc(*(line->buf + cursor_pos + charCount), stdout);
|
||||
}
|
||||
|
||||
while (charCount++ < redraw_step_forward);
|
||||
cursor_pos += redraw_step_forward;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
50
interpreters/micropython/py_readline.h
Normal file
50
interpreters/micropython/py_readline.h
Normal file
@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
* interpreters/micropython/py_readline.h
|
||||
*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_INTERPRETERS_MICROPYTHON_PY_READLINE_H
|
||||
#define __APPS_INTERPRETERS_MICROPYTHON_PY_READLINE_H 1
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define CHAR_CTRL_A (1)
|
||||
#define CHAR_CTRL_B (2)
|
||||
#define CHAR_CTRL_C (3)
|
||||
#define CHAR_CTRL_D (4)
|
||||
#define CHAR_CTRL_E (5)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
void readline_init0(void);
|
||||
int py_readline(vstr_t *line, const char *prompt);
|
||||
|
||||
#endif /* __APPS_INTERPRETERS_MICROPYTHON_PY_READLINE_H */
|
404
interpreters/micropython/pyexec.c
Normal file
404
interpreters/micropython/pyexec.c
Normal file
@ -0,0 +1,404 @@
|
||||
/****************************************************************************
|
||||
* interpreters/micropython/py_readline.c
|
||||
*
|
||||
* This file was part of the Micro Python project, http://micropython.org/
|
||||
* and has been integrated into Nuttx by Dave Marples (dave@marples.net)
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/parsehelper.h"
|
||||
#include "py/compile.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/repl.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/pfenv.h"
|
||||
|
||||
#include "py_readline.h"
|
||||
#include "pyexec.h"
|
||||
#include "genhdr/py-version.h"
|
||||
|
||||
#define EXEC_FLAG_PRINT_EOF (1)
|
||||
#define EXEC_FLAG_ALLOW_DEBUGGING (2)
|
||||
#define EXEC_FLAG_IS_REPL (4)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
|
||||
STATIC bool repl_display_debugging_info = 0;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* parses, compiles and executes the code in the lexer
|
||||
* frees the lexer before returning
|
||||
* EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after
|
||||
* exception output
|
||||
* EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after
|
||||
* executing the code
|
||||
* EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile)
|
||||
*/
|
||||
|
||||
STATIC int parse_compile_execute(mp_lexer_t * lex,
|
||||
mp_parse_input_kind_t input_kind,
|
||||
int exec_flags)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mp_parse_error_kind_t parse_error_kind;
|
||||
mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind);
|
||||
qstr source_name = lex->source_name;
|
||||
|
||||
/* check for parse error */
|
||||
|
||||
if (pn == MP_PARSE_NODE_NULL)
|
||||
{
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF)
|
||||
{
|
||||
fprintf(stdout, "\x04");
|
||||
}
|
||||
|
||||
mp_parse_show_exception(lex, parse_error_kind);
|
||||
mp_lexer_free(lex);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
mp_lexer_free(lex);
|
||||
|
||||
mp_obj_t module_fun =
|
||||
mp_compile(pn, source_name, MP_EMIT_OPT_NONE,
|
||||
exec_flags & EXEC_FLAG_IS_REPL);
|
||||
|
||||
/* check for compile error */
|
||||
|
||||
if (mp_obj_is_exception_instance(module_fun))
|
||||
{
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF)
|
||||
{
|
||||
fprintf(stdout, "\x04");
|
||||
}
|
||||
|
||||
mp_obj_print_exception(printf_wrapper, NULL, module_fun);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* execute code */
|
||||
|
||||
nlr_buf_t nlr;
|
||||
|
||||
struct timespec start;
|
||||
clock_gettime(CLOCK_REALTIME, &start);
|
||||
|
||||
if (nlr_push(&nlr) == 0)
|
||||
{
|
||||
// mp_hal_set_interrupt_char(CHAR_CTRL_C); /* allow ctrl-C to interrupt us */
|
||||
mp_call_function_0(module_fun);
|
||||
// mp_hal_set_interrupt_char(-1); /* disable interrupt */
|
||||
|
||||
nlr_pop();
|
||||
ret = 1;
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF)
|
||||
{
|
||||
fprintf(stdout, "\x04");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* uncaught exception */
|
||||
|
||||
// mp_hal_set_interrupt_char(-1); /* disable interrupt */
|
||||
|
||||
/* print EOF after normal output */
|
||||
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF)
|
||||
{
|
||||
fprintf(stdout, "\x04");
|
||||
}
|
||||
|
||||
/* check for SystemExit */
|
||||
|
||||
if (mp_obj_is_subclass_fast
|
||||
(mp_obj_get_type((mp_obj_t) nlr.ret_val), &mp_type_SystemExit))
|
||||
{
|
||||
/* at the moment, the value of SystemExit is unused */
|
||||
|
||||
ret = PYEXEC_FORCED_EXIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t) nlr.ret_val);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* display debugging info if wanted */
|
||||
|
||||
if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info)
|
||||
{
|
||||
struct timespec endTime;
|
||||
clock_gettime(CLOCK_REALTIME, &endTime);
|
||||
|
||||
mp_uint_t ticks = ((endTime.tv_sec - start.tv_sec) * 1000) +
|
||||
((((endTime.tv_nsec / 1000000) + 1000) -
|
||||
(start.tv_nsec / 1000000)) % 1000);
|
||||
|
||||
printf("took " UINT_FMT " ms\n", ticks);
|
||||
|
||||
/* qstr info */
|
||||
|
||||
{
|
||||
mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
|
||||
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
|
||||
printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT
|
||||
"\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT
|
||||
"\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF)
|
||||
{
|
||||
fprintf(stdout, "\x04");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pyexec_raw_repl(void)
|
||||
{
|
||||
vstr_t line;
|
||||
vstr_init(&line, 32);
|
||||
|
||||
raw_repl_reset:
|
||||
fprintf(stdout, "raw REPL; CTRL-B to exit\r\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
vstr_reset(&line);
|
||||
fputc('>', stdout);
|
||||
fflush(stdout);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char c = getc(stdin);
|
||||
if (c == CHAR_CTRL_A)
|
||||
{
|
||||
/* reset raw REPL */
|
||||
|
||||
goto raw_repl_reset;
|
||||
}
|
||||
else if (c == CHAR_CTRL_B)
|
||||
{
|
||||
/* change to friendly REPL */
|
||||
|
||||
fprintf(stdout, "\r\n");
|
||||
vstr_clear(&line);
|
||||
pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
|
||||
return 0;
|
||||
}
|
||||
else if (c == CHAR_CTRL_C)
|
||||
{
|
||||
/* clear line */
|
||||
|
||||
vstr_reset(&line);
|
||||
}
|
||||
else if (c == CHAR_CTRL_D)
|
||||
{
|
||||
/* input finished */
|
||||
|
||||
break;
|
||||
}
|
||||
else if (c <= 127)
|
||||
{
|
||||
/* let through any other ASCII character */
|
||||
|
||||
vstr_add_char(&line, c);
|
||||
fputc(c, stdout);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* indicate reception of command */
|
||||
|
||||
fprintf(stdout, "OK");
|
||||
|
||||
if (line.len == 0)
|
||||
{
|
||||
/* exit for a soft reset */
|
||||
|
||||
fprintf(stdout, "\r\n");
|
||||
vstr_clear(&line);
|
||||
return PYEXEC_FORCED_EXIT;
|
||||
}
|
||||
|
||||
mp_lexer_t *lex =
|
||||
mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0);
|
||||
if (lex == NULL)
|
||||
{
|
||||
printf("\x04MemoryError\n\x04");
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret =
|
||||
parse_compile_execute(lex, MP_PARSE_FILE_INPUT,
|
||||
EXEC_FLAG_PRINT_EOF);
|
||||
if (ret & PYEXEC_FORCED_EXIT)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
int pyexec_friendly_repl(void)
|
||||
{
|
||||
vstr_t line;
|
||||
vstr_init(&line, 32);
|
||||
|
||||
friendly_repl_reset:
|
||||
fprintf(stdout,
|
||||
"Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE
|
||||
"; NuttX with " CONFIG_ARCH_FAMILY " " CONFIG_ARCH_CHIP "\r\n");
|
||||
fprintf(stdout, "Type \"help()\" for more information.\r\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
input_restart:
|
||||
vstr_reset(&line);
|
||||
int ret = py_readline(&line, ">>> ");
|
||||
|
||||
if (ret == CHAR_CTRL_A)
|
||||
{
|
||||
/* change to raw REPL */
|
||||
|
||||
fprintf(stdout, "\r\n");
|
||||
vstr_clear(&line);
|
||||
pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;
|
||||
return 0;
|
||||
}
|
||||
else if (ret == CHAR_CTRL_B)
|
||||
{
|
||||
/* reset friendly REPL */
|
||||
|
||||
fprintf(stdout, "\r\n");
|
||||
goto friendly_repl_reset;
|
||||
}
|
||||
else if (ret == CHAR_CTRL_C)
|
||||
{
|
||||
/* break */
|
||||
|
||||
fprintf(stdout, "\r\n");
|
||||
continue;
|
||||
}
|
||||
else if (ret == CHAR_CTRL_D)
|
||||
{
|
||||
/* exit for a soft reset */
|
||||
|
||||
fprintf(stdout, "\r\n");
|
||||
vstr_clear(&line);
|
||||
return PYEXEC_FORCED_EXIT;
|
||||
}
|
||||
else if (vstr_len(&line) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
while (mp_repl_continue_with_input(vstr_str(&line)))
|
||||
{
|
||||
vstr_add_char(&line, '\n');
|
||||
int ret = py_readline(&line, "... ");
|
||||
if (ret == CHAR_CTRL_C)
|
||||
{
|
||||
/* cancel everything */
|
||||
|
||||
fprintf(stdout, "\r\n");
|
||||
goto input_restart;
|
||||
}
|
||||
else if (ret == CHAR_CTRL_D)
|
||||
{
|
||||
/* stop entering compound statement */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mp_lexer_t *lex =
|
||||
mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line),
|
||||
vstr_len(&line), 0);
|
||||
if (lex == NULL)
|
||||
{
|
||||
printf("MemoryError\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret =
|
||||
parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT,
|
||||
EXEC_FLAG_ALLOW_DEBUGGING |
|
||||
EXEC_FLAG_IS_REPL);
|
||||
if (ret & PYEXEC_FORCED_EXIT)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
int pyexec_file(const char *filename)
|
||||
{
|
||||
mp_lexer_t *lex = mp_lexer_new_from_file(filename);
|
||||
|
||||
if (lex == NULL)
|
||||
{
|
||||
printf("could not open file '%s' for reading\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
return parse_compile_execute(lex, MP_PARSE_FILE_INPUT, 0);
|
||||
}
|
||||
|
||||
mp_obj_t pyb_set_repl_info(mp_obj_t o_value)
|
||||
{
|
||||
repl_display_debugging_info = mp_obj_get_int(o_value);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj, pyb_set_repl_info);
|
65
interpreters/micropython/pyexec.h
Normal file
65
interpreters/micropython/pyexec.h
Normal file
@ -0,0 +1,65 @@
|
||||
/****************************************************************************
|
||||
* examples/micropython/pexec.h
|
||||
*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_INTERPRETERS_MICROPYTHON_PYEXEC_H
|
||||
#define __APPS_INTERPRETERS_MICROPYTHON_PYEXEC_H 1
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define PYEXEC_FORCED_EXIT (0x100)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PYEXEC_MODE_RAW_REPL,
|
||||
PYEXEC_MODE_FRIENDLY_REPL,
|
||||
} pyexec_mode_kind_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
extern pyexec_mode_kind_t pyexec_mode_kind;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int pyexec_raw_repl(void);
|
||||
int pyexec_friendly_repl(void);
|
||||
int pyexec_file(const char *filename);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_set_repl_info_obj);
|
||||
|
||||
#endif /* __APPS_INTERPRETERS_MICROPYTHON_PYEXEC_H */
|
1
interpreters/micropython/qstrdefsport.h
Normal file
1
interpreters/micropython/qstrdefsport.h
Normal file
@ -0,0 +1 @@
|
||||
/* qstrs specific to this port */
|
Loading…
x
Reference in New Issue
Block a user