From 76e4a1833832223212995fa9e1211d234c795939 Mon Sep 17 00:00:00 2001 From: gemu Date: Fri, 22 Nov 2024 07:41:58 +0100 Subject: [PATCH] Delete lib/libesp32/Berry directory --- lib/libesp32/Berry/LICENSE | 21 - lib/libesp32/Berry/Makefile | 93 - lib/libesp32/Berry/README.md | 161 -- lib/libesp32/Berry/berry-logo.png | Bin 11325 -> 0 bytes lib/libesp32/Berry/default/be_modtab.c | 353 --- lib/libesp32/Berry/default/berry_conf.h | 323 --- lib/libesp32/Berry/examples/anon_func.be | 20 - lib/libesp32/Berry/examples/bigloop.be | 15 - lib/libesp32/Berry/examples/bintree.be | 60 - lib/libesp32/Berry/examples/calcpi.be | 16 - lib/libesp32/Berry/examples/exception.be | 12 - lib/libesp32/Berry/examples/fib_rec.be | 12 - lib/libesp32/Berry/examples/guess_number.be | 26 - lib/libesp32/Berry/examples/json.be | 4 - lib/libesp32/Berry/examples/lambda.be | 8 - lib/libesp32/Berry/examples/listdir.be | 16 - lib/libesp32/Berry/examples/qsort.be | 42 - lib/libesp32/Berry/examples/repl.be | 61 - lib/libesp32/Berry/examples/string.be | 32 - lib/libesp32/Berry/examples/strmod.be | 7 - lib/libesp32/Berry/gen.sh | 8 - lib/libesp32/Berry/library.json | 32 - lib/libesp32/Berry/src/be_api.c | 1179 --------- lib/libesp32/Berry/src/be_baselib.c | 552 ---- lib/libesp32/Berry/src/be_bytecode.c | 634 ----- lib/libesp32/Berry/src/be_bytecode.h | 19 - lib/libesp32/Berry/src/be_byteslib.c | 1907 ------------- lib/libesp32/Berry/src/be_class.c | 374 --- lib/libesp32/Berry/src/be_class.h | 78 - lib/libesp32/Berry/src/be_code.c | 976 ------- lib/libesp32/Berry/src/be_code.h | 44 - lib/libesp32/Berry/src/be_constobj.h | 508 ---- lib/libesp32/Berry/src/be_debug.c | 418 --- lib/libesp32/Berry/src/be_debug.h | 28 - lib/libesp32/Berry/src/be_debuglib.c | 289 -- lib/libesp32/Berry/src/be_decoder.h | 74 - lib/libesp32/Berry/src/be_exec.c | 522 ---- lib/libesp32/Berry/src/be_exec.h | 63 - lib/libesp32/Berry/src/be_filelib.c | 263 -- lib/libesp32/Berry/src/be_func.c | 183 -- lib/libesp32/Berry/src/be_func.h | 27 - lib/libesp32/Berry/src/be_gc.c | 613 ----- lib/libesp32/Berry/src/be_gc.h | 79 - lib/libesp32/Berry/src/be_gclib.c | 47 - lib/libesp32/Berry/src/be_globallib.c | 100 - lib/libesp32/Berry/src/be_introspectlib.c | 278 -- lib/libesp32/Berry/src/be_jsonlib.c | 565 ---- lib/libesp32/Berry/src/be_lexer.c | 871 ------ lib/libesp32/Berry/src/be_lexer.h | 140 - lib/libesp32/Berry/src/be_libs.c | 29 - lib/libesp32/Berry/src/be_libs.h | 15 - lib/libesp32/Berry/src/be_list.c | 207 -- lib/libesp32/Berry/src/be_list.h | 39 - lib/libesp32/Berry/src/be_listlib.c | 556 ---- lib/libesp32/Berry/src/be_map.c | 354 --- lib/libesp32/Berry/src/be_map.h | 61 - lib/libesp32/Berry/src/be_maplib.c | 265 -- lib/libesp32/Berry/src/be_mathlib.c | 438 --- lib/libesp32/Berry/src/be_mem.c | 372 --- lib/libesp32/Berry/src/be_mem.h | 37 - lib/libesp32/Berry/src/be_module.c | 498 ---- lib/libesp32/Berry/src/be_module.h | 43 - lib/libesp32/Berry/src/be_object.c | 84 - lib/libesp32/Berry/src/be_object.h | 267 -- lib/libesp32/Berry/src/be_opcodes.h | 57 - lib/libesp32/Berry/src/be_oslib.c | 271 -- lib/libesp32/Berry/src/be_parser.c | 1838 ------------- lib/libesp32/Berry/src/be_parser.h | 91 - lib/libesp32/Berry/src/be_rangelib.c | 187 -- lib/libesp32/Berry/src/be_repl.c | 106 - lib/libesp32/Berry/src/be_repl.h | 26 - lib/libesp32/Berry/src/be_solidifylib.c | 886 ------- lib/libesp32/Berry/src/be_strictlib.c | 40 - lib/libesp32/Berry/src/be_string.c | 326 --- lib/libesp32/Berry/src/be_string.h | 63 - lib/libesp32/Berry/src/be_strlib.c | 1069 -------- lib/libesp32/Berry/src/be_strlib.h | 34 - lib/libesp32/Berry/src/be_sys.h | 48 - lib/libesp32/Berry/src/be_syslib.c | 36 - lib/libesp32/Berry/src/be_timelib.c | 72 - lib/libesp32/Berry/src/be_var.c | 174 -- lib/libesp32/Berry/src/be_var.h | 31 - lib/libesp32/Berry/src/be_vector.c | 157 -- lib/libesp32/Berry/src/be_vector.h | 43 - lib/libesp32/Berry/src/be_vm.c | 1419 ---------- lib/libesp32/Berry/src/be_vm.h | 169 -- lib/libesp32/Berry/src/berry.h | 2355 ----------------- lib/libesp32/Berry/src/berry_conf.h | 1 - lib/libesp32/Berry/testall.be | 44 - lib/libesp32/Berry/tests/assignment.be | 34 - lib/libesp32/Berry/tests/bool.be | 53 - lib/libesp32/Berry/tests/bytes.be | 327 --- lib/libesp32/Berry/tests/bytes_b64.be | 15 - lib/libesp32/Berry/tests/bytes_fixed.be | 68 - lib/libesp32/Berry/tests/checkspace.be | 35 - lib/libesp32/Berry/tests/class.be | 60 - lib/libesp32/Berry/tests/class_const.be | 122 - lib/libesp32/Berry/tests/closure.be | 16 - lib/libesp32/Berry/tests/compiler.be | 80 - lib/libesp32/Berry/tests/compound.be | 28 - lib/libesp32/Berry/tests/cond_expr.be | 10 - lib/libesp32/Berry/tests/debug.be | 29 - lib/libesp32/Berry/tests/exceptions.be | 7 - lib/libesp32/Berry/tests/for.be | 44 - lib/libesp32/Berry/tests/function.be | 12 - lib/libesp32/Berry/tests/global.be | 43 - lib/libesp32/Berry/tests/introspect.be | 66 - lib/libesp32/Berry/tests/json.be | 95 - lib/libesp32/Berry/tests/lexer.be | 65 - lib/libesp32/Berry/tests/lexergc.be | 12 - lib/libesp32/Berry/tests/list.be | 140 - lib/libesp32/Berry/tests/member_indirect.be | 75 - lib/libesp32/Berry/tests/os.be | 51 - lib/libesp32/Berry/tests/overload.be | 14 - lib/libesp32/Berry/tests/relop.be | 40 - lib/libesp32/Berry/tests/string.be | 215 -- lib/libesp32/Berry/tests/subobject.be | 29 - lib/libesp32/Berry/tests/suffix.be | 28 - lib/libesp32/Berry/tests/super_auto.be | 132 - lib/libesp32/Berry/tests/super_leveled.be | 43 - lib/libesp32/Berry/tests/vararg.be | 14 - lib/libesp32/Berry/tests/virtual_methods.be | 72 - lib/libesp32/Berry/tests/virtual_methods2.be | 39 - .../Berry/tools/grammar/berry.bytecode | 92 - lib/libesp32/Berry/tools/grammar/berry.ebnf | 49 - .../Berry/tools/grammar/const_obj.ebnf | 11 - lib/libesp32/Berry/tools/grammar/json.ebnf | 5 - 127 files changed, 27231 deletions(-) delete mode 100644 lib/libesp32/Berry/LICENSE delete mode 100755 lib/libesp32/Berry/Makefile delete mode 100644 lib/libesp32/Berry/README.md delete mode 100644 lib/libesp32/Berry/berry-logo.png delete mode 100644 lib/libesp32/Berry/default/be_modtab.c delete mode 100644 lib/libesp32/Berry/default/berry_conf.h delete mode 100644 lib/libesp32/Berry/examples/anon_func.be delete mode 100644 lib/libesp32/Berry/examples/bigloop.be delete mode 100644 lib/libesp32/Berry/examples/bintree.be delete mode 100644 lib/libesp32/Berry/examples/calcpi.be delete mode 100644 lib/libesp32/Berry/examples/exception.be delete mode 100644 lib/libesp32/Berry/examples/fib_rec.be delete mode 100644 lib/libesp32/Berry/examples/guess_number.be delete mode 100644 lib/libesp32/Berry/examples/json.be delete mode 100644 lib/libesp32/Berry/examples/lambda.be delete mode 100644 lib/libesp32/Berry/examples/listdir.be delete mode 100644 lib/libesp32/Berry/examples/qsort.be delete mode 100644 lib/libesp32/Berry/examples/repl.be delete mode 100644 lib/libesp32/Berry/examples/string.be delete mode 100644 lib/libesp32/Berry/examples/strmod.be delete mode 100755 lib/libesp32/Berry/gen.sh delete mode 100644 lib/libesp32/Berry/library.json delete mode 100644 lib/libesp32/Berry/src/be_api.c delete mode 100644 lib/libesp32/Berry/src/be_baselib.c delete mode 100644 lib/libesp32/Berry/src/be_bytecode.c delete mode 100644 lib/libesp32/Berry/src/be_bytecode.h delete mode 100644 lib/libesp32/Berry/src/be_byteslib.c delete mode 100644 lib/libesp32/Berry/src/be_class.c delete mode 100644 lib/libesp32/Berry/src/be_class.h delete mode 100644 lib/libesp32/Berry/src/be_code.c delete mode 100644 lib/libesp32/Berry/src/be_code.h delete mode 100644 lib/libesp32/Berry/src/be_constobj.h delete mode 100644 lib/libesp32/Berry/src/be_debug.c delete mode 100644 lib/libesp32/Berry/src/be_debug.h delete mode 100644 lib/libesp32/Berry/src/be_debuglib.c delete mode 100644 lib/libesp32/Berry/src/be_decoder.h delete mode 100644 lib/libesp32/Berry/src/be_exec.c delete mode 100644 lib/libesp32/Berry/src/be_exec.h delete mode 100644 lib/libesp32/Berry/src/be_filelib.c delete mode 100644 lib/libesp32/Berry/src/be_func.c delete mode 100644 lib/libesp32/Berry/src/be_func.h delete mode 100644 lib/libesp32/Berry/src/be_gc.c delete mode 100644 lib/libesp32/Berry/src/be_gc.h delete mode 100644 lib/libesp32/Berry/src/be_gclib.c delete mode 100644 lib/libesp32/Berry/src/be_globallib.c delete mode 100644 lib/libesp32/Berry/src/be_introspectlib.c delete mode 100644 lib/libesp32/Berry/src/be_jsonlib.c delete mode 100644 lib/libesp32/Berry/src/be_lexer.c delete mode 100644 lib/libesp32/Berry/src/be_lexer.h delete mode 100644 lib/libesp32/Berry/src/be_libs.c delete mode 100644 lib/libesp32/Berry/src/be_libs.h delete mode 100644 lib/libesp32/Berry/src/be_list.c delete mode 100644 lib/libesp32/Berry/src/be_list.h delete mode 100644 lib/libesp32/Berry/src/be_listlib.c delete mode 100644 lib/libesp32/Berry/src/be_map.c delete mode 100644 lib/libesp32/Berry/src/be_map.h delete mode 100644 lib/libesp32/Berry/src/be_maplib.c delete mode 100644 lib/libesp32/Berry/src/be_mathlib.c delete mode 100644 lib/libesp32/Berry/src/be_mem.c delete mode 100644 lib/libesp32/Berry/src/be_mem.h delete mode 100644 lib/libesp32/Berry/src/be_module.c delete mode 100644 lib/libesp32/Berry/src/be_module.h delete mode 100644 lib/libesp32/Berry/src/be_object.c delete mode 100644 lib/libesp32/Berry/src/be_object.h delete mode 100644 lib/libesp32/Berry/src/be_opcodes.h delete mode 100644 lib/libesp32/Berry/src/be_oslib.c delete mode 100644 lib/libesp32/Berry/src/be_parser.c delete mode 100644 lib/libesp32/Berry/src/be_parser.h delete mode 100644 lib/libesp32/Berry/src/be_rangelib.c delete mode 100644 lib/libesp32/Berry/src/be_repl.c delete mode 100644 lib/libesp32/Berry/src/be_repl.h delete mode 100644 lib/libesp32/Berry/src/be_solidifylib.c delete mode 100644 lib/libesp32/Berry/src/be_strictlib.c delete mode 100644 lib/libesp32/Berry/src/be_string.c delete mode 100644 lib/libesp32/Berry/src/be_string.h delete mode 100644 lib/libesp32/Berry/src/be_strlib.c delete mode 100644 lib/libesp32/Berry/src/be_strlib.h delete mode 100644 lib/libesp32/Berry/src/be_sys.h delete mode 100644 lib/libesp32/Berry/src/be_syslib.c delete mode 100644 lib/libesp32/Berry/src/be_timelib.c delete mode 100644 lib/libesp32/Berry/src/be_var.c delete mode 100644 lib/libesp32/Berry/src/be_var.h delete mode 100644 lib/libesp32/Berry/src/be_vector.c delete mode 100644 lib/libesp32/Berry/src/be_vector.h delete mode 100644 lib/libesp32/Berry/src/be_vm.c delete mode 100644 lib/libesp32/Berry/src/be_vm.h delete mode 100644 lib/libesp32/Berry/src/berry.h delete mode 100644 lib/libesp32/Berry/src/berry_conf.h delete mode 100755 lib/libesp32/Berry/testall.be delete mode 100644 lib/libesp32/Berry/tests/assignment.be delete mode 100644 lib/libesp32/Berry/tests/bool.be delete mode 100644 lib/libesp32/Berry/tests/bytes.be delete mode 100644 lib/libesp32/Berry/tests/bytes_b64.be delete mode 100644 lib/libesp32/Berry/tests/bytes_fixed.be delete mode 100644 lib/libesp32/Berry/tests/checkspace.be delete mode 100644 lib/libesp32/Berry/tests/class.be delete mode 100644 lib/libesp32/Berry/tests/class_const.be delete mode 100644 lib/libesp32/Berry/tests/closure.be delete mode 100644 lib/libesp32/Berry/tests/compiler.be delete mode 100644 lib/libesp32/Berry/tests/compound.be delete mode 100644 lib/libesp32/Berry/tests/cond_expr.be delete mode 100644 lib/libesp32/Berry/tests/debug.be delete mode 100644 lib/libesp32/Berry/tests/exceptions.be delete mode 100644 lib/libesp32/Berry/tests/for.be delete mode 100644 lib/libesp32/Berry/tests/function.be delete mode 100644 lib/libesp32/Berry/tests/global.be delete mode 100644 lib/libesp32/Berry/tests/introspect.be delete mode 100644 lib/libesp32/Berry/tests/json.be delete mode 100644 lib/libesp32/Berry/tests/lexer.be delete mode 100644 lib/libesp32/Berry/tests/lexergc.be delete mode 100644 lib/libesp32/Berry/tests/list.be delete mode 100644 lib/libesp32/Berry/tests/member_indirect.be delete mode 100644 lib/libesp32/Berry/tests/os.be delete mode 100644 lib/libesp32/Berry/tests/overload.be delete mode 100644 lib/libesp32/Berry/tests/relop.be delete mode 100644 lib/libesp32/Berry/tests/string.be delete mode 100644 lib/libesp32/Berry/tests/subobject.be delete mode 100644 lib/libesp32/Berry/tests/suffix.be delete mode 100644 lib/libesp32/Berry/tests/super_auto.be delete mode 100644 lib/libesp32/Berry/tests/super_leveled.be delete mode 100644 lib/libesp32/Berry/tests/vararg.be delete mode 100644 lib/libesp32/Berry/tests/virtual_methods.be delete mode 100644 lib/libesp32/Berry/tests/virtual_methods2.be delete mode 100755 lib/libesp32/Berry/tools/grammar/berry.bytecode delete mode 100644 lib/libesp32/Berry/tools/grammar/berry.ebnf delete mode 100755 lib/libesp32/Berry/tools/grammar/const_obj.ebnf delete mode 100644 lib/libesp32/Berry/tools/grammar/json.ebnf diff --git a/lib/libesp32/Berry/LICENSE b/lib/libesp32/Berry/LICENSE deleted file mode 100644 index 609969272cbf..000000000000 --- a/lib/libesp32/Berry/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018-2020 Guan Wenliang - -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. diff --git a/lib/libesp32/Berry/Makefile b/lib/libesp32/Berry/Makefile deleted file mode 100755 index 2d33069fbbef..000000000000 --- a/lib/libesp32/Berry/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -CFLAGS = -Wall -Wextra -std=c99 -O2 -Wno-zero-length-array -Wno-empty-translation-unit -DUSE_BERRY_INT64 -DEBUG_FLAGS = -O0 -g -DBE_DEBUG -TEST_FLAGS = $(DEBUG_FLAGS) --coverage -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -LIBS = -lm -TARGET = berry -CC = gcc -MKDIR = mkdir -LFLAGS = - -INCPATH = src default ../re1.5 ../berry_mapping/src ../berry_int64/src generate -SRCPATH = src default ../re1.5 ../berry_mapping/src ../berry_int64/src -GENERATE = generate -CONFIG = default/berry_conf.h -COC = tools/coc/coc -CONST_TAB = $(GENERATE)/be_const_strtab.h - -ifeq ($(OS), Windows_NT) # Windows - CFLAGS += -Wno-format # for "%I64d" warning - LFLAGS += -Wl,--out-implib,berry.lib # export symbols lib for dll linked - TARGET := $(TARGET).exe - PYTHON ?= python # only for windows and need python3 - COC := $(PYTHON) $(COC) -else - CFLAGS += -DUSE_READLINE_LIB - LIBS += -lreadline -ldl - OS := $(shell uname) - ifeq ($(OS), Linux) - LFLAGS += -Wl,--export-dynamic - endif -endif - -ifneq ($(V), 1) - Q=@ - MSG=@echo -else - MSG=@true -endif - -SRCS = $(foreach dir, $(SRCPATH), $(wildcard $(dir)/*.c)) -OBJS = $(patsubst %.c, %.o, $(SRCS)) -DEPS = $(patsubst %.c, %.d, $(SRCS)) -INCFLAGS = $(foreach dir, $(INCPATH), -I"$(dir)") - -.PHONY : clean - -all: $(TARGET) - -debug: CFLAGS += $(DEBUG_FLAGS) -debug: all - -test: CFLAGS += $(TEST_FLAGS) -test: LFLAGS += $(TEST_FLAGS) -test: all - $(MSG) [Run Testcases...] - $(Q) ./testall.be - $(Q) $(RM) */*.gcno */*.gcda - -$(TARGET): $(OBJS) - $(MSG) [Linking...] - $(Q) $(CC) $(OBJS) $(LFLAGS) $(LIBS) -o $@ - $(MSG) done - -$(OBJS): %.o: %.c - $(MSG) [Compile] $< - $(Q) $(CC) -MM $(CFLAGS) $(INCFLAGS) -MT"$*.d" -MT"$(<:.c=.o)" $< > $*.d - $(Q) $(CC) $(CFLAGS) $(INCFLAGS) -c $< -o $@ - -sinclude $(DEPS) - -$(OBJS): $(CONST_TAB) - -$(CONST_TAB): $(GENERATE) $(SRCS) $(CONFIG) - $(MSG) [Prebuild] generate resources - $(Q) $(COC) -o $(GENERATE) $(SRCPATH) -c $(CONFIG) - -$(GENERATE): - $(Q) $(MKDIR) $(GENERATE) - -install: - cp $(TARGET) /usr/local/bin - -uninstall: - $(RM) /usr/local/bin/$(TARGET) - -prebuild: $(GENERATE) - $(MSG) [Prebuild] generate resources - $(Q) $(COC) -o $(GENERATE) $(SRCPATH) -c $(CONFIG) - $(MSG) done - -clean: - $(MSG) [Clean...] - $(Q) $(RM) $(OBJS) $(DEPS) $(GENERATE)/* berry.lib - $(MSG) done diff --git a/lib/libesp32/Berry/README.md b/lib/libesp32/Berry/README.md deleted file mode 100644 index aef02a192c73..000000000000 --- a/lib/libesp32/Berry/README.md +++ /dev/null @@ -1,161 +0,0 @@ -

-

- Berry -

-

The Berry Script Language.

-

- -## Introduction - -Berry is a ultra-lightweight dynamically typed embedded scripting language. It is designed for lower-performance embedded devices. The Berry interpreter-core's code size is less than 40KiB and can run on less than 4KiB heap (on ARM Cortex M4 CPU, Thumb ISA and ARMCC compiler). - -The interpreter of Berry include a one-pass compiler and register-based VM, all the code is written in ANSI C99. In Berry not every type is a class object. Some simple value types, such as int, real, boolean and string are not class object, but list, map and range are class object. This is a consideration about performance. -Register-based VM is the same meaning as above. - -Berry has the following advantages: - -* Lightweight: A well-optimized interpreter with very little resources. Ideal for use in microprocessors. -* Fast: optimized one-pass bytecode compiler and register-based virtual machine. -* Powerful: supports imperative programming, object-oriented programming, functional programming. -* Flexible: Berry is a dynamic type script, and it's intended for embedding in applications. It can provide good dynamic scalability for the host system. -* Simple: simple and natural syntax, support garbage collection, and easy to use FFI (foreign function interface). -* RAM saving: With compile-time object construction, most of the constant objects are stored in read-only code data segments, so the RAM usage of the interpreter is very low when it starts. - -## Documents - -Reference Manual: [Wiki](https://github.com/berry-lang/berry/wiki/Reference) - -Short Manual (slightly outdated): [berry_short_manual.pdf](https://github.com/Skiars/berry_doc/releases/download/latest/berry_short_manual.pdf). - -Berry's EBNF grammar definition: [tools/grammar/berry.ebnf](./tools/grammar/berry.ebnf) - -## Features - -* Base Type - * Nil: `nil` - * Boolean: `true` and `false` - * Numerical: Integer (`int`) and Real (`real`) - * String: Single quotation-mark string and double quotation-mark string - * Class: Instance template, read only - * Instance: Object constructed by class - * Module: Read-write key-value pair table - * List: Ordered container, like `[1, 2, 3]` - * Map: Hash Map container, like `{ 'a': 1, 2: 3, 'map': {} }` - * Range: include a lower and a upper integer value, like `0..5` -* Operator and Expression - * Assign operator: `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=` - * Relational operator: `<`, `<=`, `==`, `!=`, `>`, `>=` - * Logic operator: `&&`, `||`, `!` - * Arithmetic operator: `+`, `-`, `*`, `/`, `%` - * Bitwise operator: `&`, `|`, `~`, `^`, `<<`, `>>` - * Field operator: `.` - * Subscript operator: `[]` - * Connect string operator: `+` - * Conditional operator: `? :` - * Brackets: `()` -* Control Structure - * Conditional statement: `if-else` - * Iteration statement: `while` and `for` - * Jump statement: `break` and `continue` -* Function - * Local variable and block scope - * Return statement - * Nested functions definition - * Closure based on Upvalue - * Anonymous function - * Lambda expression -* Class - * Inheritance (only public single inheritance) - * Method and Operator Overload - * Constructor method - * Destructive method -* Module Management - * Built-in module that takes almost no RAM - * Extension module support: script module, bytecode file module and shared library (like *.so, *.dll) module -* GC (Garbage collection) - * Mark-Sweep GC -* Exceptional Handling - * Throw any exception value using the `raise` statement - * Multiple catch mode -* Bytecode file support - * Export function to bytecode file - * Load the bytecode file and execute - -## Build and Run - -1. Install the readline library (Windows does not need): - - ``` bash - sudo apt install libreadline-dev # Ubuntu - brew install readline # MacOS - ``` - -2. Build (The default compiler is GCC): - - ``` - make - ``` - -3. Run: - - ``` bash - ./berry # Bash or PowerShell - berry # Windows CMD - ``` - -4. Install (Only Unix-like): - - ``` bash - make install - ``` - -## Editor plugins - -[Visual Studio Code](https://code.visualstudio.com/) plugin are in this directory: [./tools/plugins/vscode](./tools/plugins/vscode). - -## Examples - -After compiling successfully, use the `berry` command with no parameters to enter the REPL environment: -``` -Berry 0.0.1 (build in Dec 24 2018, 18:12:49) -[GCC 8.2.0] on Linux (default) -> -``` - -Now enter this code: - -``` lua -print("Hello world!") -``` - -You will see this output: - -``` -Hello world! -``` - -You can copy this code to the REPL: - -``` ruby -def fib(x) - if x <= 1 - return x - end - return fib(x - 1) + fib(x - 2) -end -fib(10) -``` - -This example code will output the result `55` and you can save the above code to a plain text file (eg test.be) and run this command: - -``` bash -./berry test.be -``` - -This will also get the correct output. - -## License - -Berry is free software distributed under the [MIT license](./LICENSE). - -The Berry interpreter partly referred to [Lua](http://www.lua.org/)'s design. View Lua's license here: http://www.lua.org/license.html. diff --git a/lib/libesp32/Berry/berry-logo.png b/lib/libesp32/Berry/berry-logo.png deleted file mode 100644 index 1eb41908963a04e02ea5aa91d264903b1c0895e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11325 zcmX9^cRbYpAOD~TDI+6Mvd5jBz2|X8WS$i{oEaINnX=CwciG`iR!C=NWn`Sl6&kX) zvSo$e`TqX!IFI-H^?tqI@7MgiU$1BUeIs2u8g?200O<4}TBZO%4h8@+$}5zlk#ct& zJL!k|F~s@_0I)J%{E@j95=m6RO@D1G{|7!U{y~m@a6sMJ#|h4*=jG@MH-$SoBYg+p zN&p}-sHdfF_VmZ^{AnMKf&6bCI+=LlhF?>I-_Fg(+28UiJx13w9m2m^Q9V3ad^YoJ z{x>&u>YZmgKBJmkG*rA|WYQXEKvF@bEL~)X99O6Njh;BMVPtOYM6-74(p*1F&26Ixs+mM}%7_X{AYe-ZHKSUsA$MZIHrv z8Bl`(#MG=(1(jk+T947U>;nV}eKr683^sOKV5!(vrwy7EM%nnZ8=zx_eEc>=A!`*)t=nB4N4aE6w9(x?&IjWN2b9dorS965e&Os9Sk! zcQKl-1Hc1369`F3>#S`-RbTQ5$AxKSpe8WhyAFtRYQeaC9Mc9G+Q_LA zEBbGqVMdf#fM-$SN|&tr_04;kyfCz|OOh#kGe!VOS)Jb22w_!O`8<8A{=WYVsLn~T zGOgBMh-50*%c;z{Y4MF-31mR$eZ_7qTX8NC^}SIw3;Ty)Ml@wF06e_L4HmB~gRt1> zrSlUo9+~~Lo-2N27i;}8v-o~-p=!+p)6%-SdTfAa(m%LjVjq&5lvga9WNGU!SUKZ9 zGv4$e1Bj6jS`GnWMiXi?CClj9!htA0HLDAYhd7wB;IaL8O_;fbztGY`b1xJM(KAKI zXu-2h)&HZZ)xIBdJtmZ%<-bjtGfE2mY6qztFHDgu&F$)flbZO46!U!vK1t+^m>kNlq50$%O|T&edCGF1qU@4C^NGqxcxXLOZLit);10qRJ*?h(VtEI`j0N^ z!V2D^eL|NB5u2yF4yRNJ&K}yVEPolvfm-12ZH2C^S~K$z*-J_{vZ$zP{%sa+I^?bY zacDgpJ-bX(E;sqWH|p|#N2_AUy1XB%+4+{qE$yX7Ez5xZ3#W_iJ=3z>_eQ^VNj|C0 zNGWXn>*%vdTNB!J?osngl?$FgWt$v@GnBY+1DSsPSMc7$s2^=-s}85r0)-)mU;0or z5%_cDep5uw`yo!}==;iy=+xp1zB}lw7WzLCx17H?TND-D`1VjGQ^NXgTRLB)vXbIT2aIFTyEVa8}E77P~g zN+2f*WB_VGo<+=KzVz`HgpG>i77M~6V=E=hoFdis6yzDySEw9cVM*?iHt%%2WEdY!^Lf_yCBh_4mD@gIMFkYog(*;OiB%)F+q z2h1Y)D=#T}rN6F~E>2N2Gn9dh|0>)({qZ*>o^w96qr4Kp+hc^ zxV?S*!B&vylxn|nn#A12ATJ|}9%Wz__d(&*6st-DSNBE|#5U(EDe@2{-_$~CFkk;& zp4WXJ;U%)%mL#e>M=a&PIN-p_5S7j1*`2VbYY#U^j5%9(=D!%*pAa4x3mrY@3c1yG zz9NE4`X$zu`9&yHgb|aPbKw9VsR{kRata0OcV{O*oF+93Kn&DV;l%Yq(fl)1o5M)( zkei4C`Wpl3vj!orXT?9 zr$2&DNWN5Bv8c_y&ivD7=&HrdHs*L}EXiBdMzM=8LqSL`O_5}qH^kRKql zptEWPWn<8ohBx~ja%+Af>1cC%DgbELCoNwhpA6XVx}F)lC*XSUx35Yj-Tu&>SL9Fe z6j$&t%C;kbDUeRr?i(FD&bT^@<2GUa?*F+Zz9oHPk(AsF8q*@RhGF6T1=3?>H6y1uYqa!Pw}emFaw9dNzmRvKO! zW!qT)BbU2W()CTwZn@G=HUCHRv3HF*0RsWBZ{{M!$l%OlIYCAi`-Cqj)V=J~6z&kV zu#*g*)*IAApaV@ujGAs2w`6c1@k<88%6R(8U2ckJ_{0o!!;Z)x_sOMu+>Wb$B10fi z+7^blewsSp|< zthTF;t(M!H$vEE_y_V?21}!4@PV?`TRcQXeV>m66Yzwn<<9z&e!LmY^)3xj-4o*ob zr%xYuL+V?1nZ9`Z;|n)f(AAzUkb|24bH?YH*M*wSM3FvueLuuw1`uBw=e-=7uWK)D*b8>#%m~ma6j#YbOtX5?)%lc`D=zv}N+z zF&!MyqkXvU8WBEQC>nZzsX_Nq+F_UNu_3s%@B0wZqWi`m%4b~=CJ27<@6$O|i_(FU$9Ik%{A4{F=!%$XdF;M`5XDScm$STTaW8Nv zZ0+lRN;gxFZ@L3-HkfOg?8Q}b#98El|5#2{hn|mG4tsArJ>2M2Kd} zLW**WYVO*y-=2Whs~tSVS%fh8l0D9BPCKuc61!es$@JJqJf+vjo9c9mq{PIt;4jg; zVYt>OvwsE;g3h`HrsWPs&!V$P;-oEb>A!auY~$V_sAGPou1+@w`|g{*TDWnn0AnXB z!dEt`F;62GQt{Ubg zCPzt|1>bs1sT2=*oBlO`v741M$;nPb_*c%RDkF|Z!YZ%izwgm98?*A4N-s3>?^j&$ z5Y9*5U+^H?(t%BKvZs$}+%#l%BMPrb zSM`_d*@za*_P2IJ|G=EIVc&40A0Ox_lcwE$MsfU$iXNwz#D2&)@;5N)JiKksYr@jk z%(?edAqWL!P(d1n4qSFFo(xI0dzY2Z(I!SrXVE+2FgUiq&EudP*022i6W1EtCVMO( z)@HC$=Bo?@35lwHgPR!lV9PsywLvwqP}&|dj$OUvk4&@yeXcK8;+I=y9X=?-gA@Zt z8sh7osw*l~EBd!b>WYOjHH||8!NTWivMujgLom8+jU}5|AC1`Mtre!;{w}Dj7#(dZ zXD6S-7JQO@7H|`O@Qt_w3vm$_Z4XK{dA-&>M*dY5#@{%S&cAhgRC%)=!?W3m>~y zz+*#F4y+^=sDk-MbD+z=2U=MsNZRvTcsV$!xQJ4SyM~Zc{rtRO?6I5ndAt4IN$yR% zb>ipxsjo?fUe9-bCmz|S)dabM-v5veF&gMdy4GA1fhG7LpHJH;mh*tq890kXGpzlJ z?8b^EJEIQmKOM@Kjc|d){PDJEw9KbA%O;D$NGiBDFHy2O$a4kW_-cqZ`aNbF8muR4 zM*LR2U^NlD!aI$2<^4hJ%o-mT9dCbG`?tWU9p9o{no_xM&Ui3{i{putFrswdb`=Q zy!QU`xH!(?<($!kVHT()SX{$GGs}x*ew}}s4rZkRSNRg^_Fx(Q+_ktUT{i|#3R0DW zZ@!*hK^5XT6)f*yd$k_@AgtILCcgJ^k&rMyur<`8Bx+3U2LO1{qpXIG-z&6DZ%A*bj=nWeiN-gn^xn_+A3|z#Zst|~OSWFNb2b$DRK!hj z@EYNW6#uaKhP^dLI%+YyY-Q{|e?z0y;476|lm+pn27ZAiu!e7JqsF9gRp93qx1w)F z!y)R8;h)V(rHik_^7jVILE5Kr=8t1D9O!7O;!oTi%P1bTJQCM?Z*ng{70U(6)2*vGk$Dl_2^90ltDz45!QO^QRA%=^z;BT00@) zg8~Di>4<+>$t`8@l?t{W`G?zFkFhaJF_RK|S?aLthx^EJCFBzOpu@P*x0G`EI(2E; zh5F1zq_L34A68uN8~Pwib%raP@*~=@gr}no%O(ed3yOxH=$iA!l_>KQlt0OXY+zH1 zO}M$l(RJarR=KRijKsyMnL96%{>*-SskgwdfP@Mu@zBBL2DyiX8u^*H!M&Z?!R?Ib zir}#fDK^i%V9H^*-oeg#4BwU?tTK8}e%heK*K}K4=V`jV!N!#br z(b`j((&aHd<7W9)tc&s_-^9fDqL2Grg$U<2Fxc`}QBd#02Onq6b=OU-?}6K5J{V0Z zpIVRgjsD81F?{UcPxtF*WO@94OfiTD?q$?0EovN&*5FD*i8#hTuXTWV+RlZ@e+mU1 zYr9uiw&39KrBf@c3Hnz=R(Ai$bH0NyJ-Rjs#I;8Wm+TFqqU$hyXV`9NGpTjoMxe^Y z5p&Nx~A~S`uDtG(LYcMm)jd~s$r@78{lq-ovrY+15M>mwj3?$ z(#&J@j?@NuHIS4ksNm)@-=~HJG)pVhqd^UBRy~Pl_4;mc4Mm$0{2<-oPnHNh#b9*9=hvcNV-%33)os~( zFeCO-KOtgQDB9`new&5_mPvYRK|!XzDyp3IW%FqYk)Gu){*{VBBOfAbOz&mEqxvFK z+rS9ygTlQtTbZpqX|n_qmZGXj>ju4%_f}1&(~%DvoGh2V@YZp+ZMw5`Ih7sAy-L&J z@zlG`_{Aha2i=w4wUlOalN$Bbs4en9lep|0HYxRoxJ6Gi1;tf0kKP*2X(Z|oM0BB) z?zf*nX*v0Dn?l$-iyT!Xi#+!+9{6a5Wx~AJy z1_GLR!N5aHA4xH1qh##SCSO03l;NchJ;V)*!8UIujj#1H?fNzwb*bo9EJ3Sb;o-++ ztu@fTAT5zxru#7$QS#c&fA zP8#eJPhR#(CdMP7Z#V?BbDz438Y%wHartY5z5J>ZD{f7csb0^=7-nJi6bwPveQ;)l zFRqsIuSu7K%;@qorTSdEdyagTTD{cl6;%Y_?=Nz%bn z3Ke@inq74WuC6rv>$ZZ~oqasEGJiR#u+MoCv|LB3==YYuQrD&VL?gZEvhDBjG5Y_S znP^}vcrYb`$>a<0>P~HlA87jW)m3VC6P9bSW;ghS{PG+rL#wf2O;|{GvwBJY0j#M!2>LtF ze6!6;@!i!CHdqo~{?F!kN09nKAjN6+k`mUOA|uLB3$~MN%G(~37uy&^@Z~FUeV4s; zQ1xlYvxOH-O9Sj|FvO0cKK9tAd|2pHpSQJK^%No&n2Z}h2paxLvr+r$eSyNIl6yH# zH5Yuc&|qkRZ}W8Zt*0^=BN%z1WoGX^L|Se|$tyvw@+FB;arSkFb$bhA)rrbu?QhbP z&%~g6PBHei@hj@uiygZ=Z+mNo_q~up~^g;vz_k8%+}cNAD-pj6MiTe|FbS~cVPGXl~CmM6@_00yQdyp zgLPS2!GnWCo{!ii1cjA#hu^IY?yuRhV(7vb2d|#o00#$mT$9<6su!t^k8_)N;o4n# z@GO4ER&tV>jo*Y^C5^?Bh?BCt4E2<5VIuzOhY@(CSX+rKksHB*c^0iW$40wNpqX-Zy{lr z5U%L_*nv@}>5xvXzPYBms-#q^1vhUPqBkxsR@l|DNznY1w(GxmwL5)rxE%f3{!e52mc7A0rT5ZG&Vy?o{2(9<4Zp?Ph0&%c zdD{*#VqGbzk}1+VJ*$c3Lr@_IrTVh>ZU*%%oazv-#Zmi;iUjd9(n!0IQjiX*_;cM$ zRaZ0j!y>T>E1qX^3Bh2E@rx`rLevH z?))yGwZ1HyJ&8$9goC{~$_-(}ikH_KKe?7=YTH5nV-V72_ za19PEAUzYzvlQheZL_ai+#_nZ{CsgoIuU8mF8g+3B&S`Kl04JdX!K#n>jD)GD1Uf* z2_HXxD|?eYlydR5k>uuUgdgMKs^LlMZ3VUk-JMyu#cR#}{8H2AKg6ZTcybBN}&gC3UFhA|fs?A&=8_4^q zK7AbX`Jw)?5`VCMNz>fQktOX`Kfe)>y}O0E-fe@J+T9T~l9c{xFkd{F{8uBDMb)?5 z-p*Ryxng^0esQvP<#IAU)IyL+5ju=<)PQ+zY~?mByE1<q*j5WG8u^z%b)cL|yP_Q$ED`gi79`rMVY4qLB zF~6)b3kz%6X_cGEts0xk9E&8#k7vcNztNhQ-4$=Rp6y(Dnba1TdhkiQV-k+AHp@R! zi`=!PhU#Uo!at4wc{TlH!PYR-!(}t3tcVra=3ZCrva+A;9v8Y{btE2t&zF&q88|GX zH*Q*==90Onjfj6Y=29YT*7{$Gsn@+e`Q;Qo2E9ypwC@6(MSnx}CnW57P4Y?&)qR zp41qsR^QzO8B&dWXGTbH?;%>_{JSSUkNChs4Bvd(A)>Q%C{16fzBglb-7-4myqDRA zFDL%$AjB5koqmFEg;|LeLXpxkSpTqVZdUAroC z!_O#EKjPXKi!O{?-%J})@4D_K#84y~?DiBJ56lj=A+r4CK=CV5FK;-4QDV@&X_F+a zpwKC^jo)>OuWhHoqzkUHM_#|o5KX>YECB3p6d0HnBH4_E_UPV z)A;1=E<1LB6-v?qLamM?ZUlH({} zvg=6QWEN+@ttgy%dN%E-t;oZsS_y>0BeCsCdW`Au_0(3ds7zG!yuKAIK$_-$Pto0p zsNRLvH1wb-otCyLQ+MnDQk5V6vqvZXI!A;|aI*3(1bD=LBzQIW`wPsjcx77Cjr!Qt zgj$eb(C&KEp6v|@=FWwy$1}vltx$Idk}K zc1o~%Xvty(O`!}^}lY6fUMoPCD+Bn0bTK)Ys z!@C)gdW!7u;!#3~WH>QIkK4*lXUv8S5i#q z&o4q;PDv@*R%sjd#}Mga_wCT%PBz9bs)1%O3O;pzduIiN+4or)R#!whN`)o8(=ir% zod$J{@ko9065bzN+uFXqa+-|?cQD(9Y^-X1ghD~0?<^$eOr;fep+9kFjpyczv#iQZ zIX=yG6Q3o-%1Y~8%gSD-P{Hm8i_#8Wg5SBy$uCfJomcE@`TYaNCO`o)>-I2WpoLe{nI2Btn|NIb`I<{qhz1p|Zhp4)Z(}&b z_3wy$=)GYb>&`(+%?(`i-FS{5A9+5cuEnCioyTNsATimH@Ky=LWba`7={CGM&3}2% z6UXPB`eQJ~jdm`*uD1U?)NIY?RDH3C(5;E#K_DKy1!f}gyoioB@pV@gh0eUblqghj z$kgT^DKx$#)%U-q$%B?paD%c3Mw@cM+PS1A{!?z!=L2ZwbDfZ%Of$Y`U};>53G*Hl zYXkzBhHq9dIQBIL4R6Q?oBy`E478_WDfmrTDjOVxjE^>RZ(FQzD(_wXLJNiF*QR%l zx)E9)y_Y9}L$pTj>8JNL!GHe4u44I;8z#4Ey~VWY9$OmA#cbEr(Q`WPHCE1_mA@E8 z^D|!s3Q`xsT2PWXMBD9#Yb@6*G3D|vMwug_*)t_dkz=5L0=?L0>%)c5j18Qoy2Nhu=;xK zCwTF!Kuh4QADbc9nk1BlBdIiWJBtpeE@2wr8;JXbzc*nd z|6$~KN`zC(uB&S}AZ;C8_MlZk&_w@mdRqD9Z7=C9|B^rsgkM1=GV)rJH6ywMX_rXf z44lFzjjpnhiPYhb<)lqB@0L6jEGwS__3QjKIhs>Hn)6YXhp#isa!d}~1RmZn%<`O; ztyFxR;o75I?YsL(suvNw@TQxm;OBf{RZmQNj!u5K|JrKb`O=uN7%XrMyG{j&eU4v9 z_iW}dL05d5urk{F5^g-m87;jqVXicdTm4i!y4$aB?BF2GC_IWDQ3e0>U*s;Lvkw4f zs6XXJs05^I!wO`Bi}V}tgK%ExW1H)kW`2=6hg2&5O_yswb!*6Ox3_4RA{!1y-VsLQpotl!XjqOR`c(TjT3 zpl#a@Y@q&WE7XaT1n5X{Tl%+~{g9u?C>ukhpIU5>r=THKD`^eR6!rQTveXE0@aC5z zW7mU*je?N8*E55)pBbTfWSvy*^|Bca9Y$K#L;BE3IepExF7RG9rDSNJ^IeG%KKNF% z+k;3Y6Zd5YP^h11--D;9(`cZR2eHZ*I?}zbyL&q>J77D*Q;F&;|6ZfC~Ms5VPU9-z>^BDZF zL@Gl5_$Q}#d3M^Z&+B7W=|3FOKb?ARa6uV(<2issEn*&QU6dM?YD7#t4z%foMv^6W z7zU1nzg+C*q=sThxVJkbMOO>_%PIAk$ag6fljx-L2FoSO7UTshmpDJEyXln6NCl)o zggJ(_t%+G^IUDa+bG1sHkh8Om>=U8$gpjn_DpMjbLrZEnN_I#fOh1>RCJMY|S$!iV zLc=!q2twg)TF2~}lE70PV)Dxj6Z9UAj|C%2N5#>XXS&?p926`NUBhDHf};lxAQF6ZqTp& zAL6O!a^2kzQMUhqk<@Lu6kT4Xiez|CYg|mCLA{IY=42XMPv@>SzcAM@Xt_Y}NHVip zKi9s^`chg`l#p|QB(Uwpah@Kbxfdgfvbi*?u}cpBU*6iQt#L{=XX?p~koS&*qzmbh z`g}rUz>Sp99eiSmlvuo9*Gid*cJG42NJK@rNw~tlLhrXWQh?f9AseJcouYr3P2I`c zy0TaQ{d9ssW#5w*AWw0%+vwUC|d z$kv6CQgoJ#HVHZgA#Cpu6O${=?$wbmNRMZu3S_kg#jL?vdr|B@l*}a>d1F{ae>B&|DkT z2KSDo*c3t&x;!~(^g%+L!nZCsMDXcwONwecIrka|LCo0xUSQvF54ol2UsjxD@{Ht( zrz_%KFJglPh4=r6GXDn;&Eu7#g*j!O*|Hsy1NI67(0)(>Bto)_C~*e_#+`sQ>@~ diff --git a/lib/libesp32/Berry/default/be_modtab.c b/lib/libesp32/Berry/default/be_modtab.c deleted file mode 100644 index e4f60edcc939..000000000000 --- a/lib/libesp32/Berry/default/be_modtab.c +++ /dev/null @@ -1,353 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "berry.h" -#include "../../berry_custom/src/modules.h" - -/* this file contains the declaration of the module table. */ - -/* default modules declare */ -be_extern_native_module(string); -be_extern_native_module(json); -be_extern_native_module(math); -be_extern_native_module(time); -be_extern_native_module(os); -be_extern_native_module(global); -be_extern_native_module(sys); -be_extern_native_module(debug); -be_extern_native_module(gc); -be_extern_native_module(solidify); -be_extern_native_module(introspect); -be_extern_native_module(strict); -be_extern_native_module(undefined); - -/* Berry extensions */ -be_extern_native_module(cb); - -/* Tasmota specific */ -be_extern_native_module(python_compat); -be_extern_native_module(re); -be_extern_native_module(mqtt); -be_extern_native_module(persist); -be_extern_native_module(autoconf); -be_extern_native_module(tapp); -be_extern_native_module(light); -be_extern_native_module(gpio); -be_extern_native_module(display); -be_extern_native_module(energy); -be_extern_native_module(webserver); -be_extern_native_module(flash); -be_extern_native_module(path); -be_extern_native_module(unishox); -be_extern_native_module(hue_ntv); -be_extern_native_module(hue_bridge); -be_extern_native_module(uuid); -be_extern_native_module(animate); -be_extern_native_module(partition_core); -be_extern_native_module(crc); -be_extern_native_module(crypto); -be_extern_native_module(ULP); -be_extern_native_module(TFL); -be_extern_native_module(mdns); -#ifdef USE_ZIGBEE -be_extern_native_module(zigbee); -be_extern_native_module(matter_zigbee); -#endif // USE_ZIGBEE -#ifdef USE_BERRY_CAM -be_extern_native_module(cam); -#endif // USE_BERRY_CAM -// BLE -be_extern_native_module(MI32); -be_extern_native_module(BLE); -#ifdef USE_LVGL -be_extern_native_module(lv); -be_extern_native_module(lv_extra); -be_extern_native_module(lv_tasmota); -#ifdef USE_LVGL_HASPMOTA -be_extern_native_module(haspmota); -#endif // USE_LVGL_HASPMOTA -#endif // USE_LVGL -#ifdef USE_MATTER_DEVICE -be_extern_native_module(matter); -#endif // USE_MATTER_DEVICE - -/* user-defined modules declare start */ - -/* user-defined modules declare end */ - -/* module list declaration */ -BERRY_LOCAL const bntvmodule_t* const be_module_table[] = { -/* default modules register */ -#if BE_USE_STRING_MODULE - &be_native_module(string), -#endif -#if BE_USE_JSON_MODULE - &be_native_module(json), -#endif -#if BE_USE_MATH_MODULE - &be_native_module(math), -#endif -#if BE_USE_TIME_MODULE - &be_native_module(time), -#endif -#if BE_USE_OS_MODULE - &be_native_module(os), -#endif -#if BE_USE_GLOBAL_MODULE - &be_native_module(global), -#endif -#if BE_USE_SYS_MODULE - &be_native_module(sys), -#endif -#if BE_USE_DEBUG_MODULE - &be_native_module(debug), -#endif -#if BE_USE_GC_MODULE - &be_native_module(gc), -#endif -#if BE_USE_SOLIDIFY_MODULE - &be_native_module(solidify), -#endif -#if BE_USE_INTROSPECT_MODULE - &be_native_module(introspect), -#endif -#if BE_USE_STRICT_MODULE - &be_native_module(strict), -#endif - &be_native_module(undefined), - - &be_native_module(re), -#ifdef TASMOTA - /* Berry extensions */ - &be_native_module(cb), - - /* user-defined modules register start */ - - &be_native_module(python_compat), - &be_native_module(path), - &be_native_module(mqtt), - &be_native_module(persist), -#ifdef USE_AUTOCONF - &be_native_module(autoconf), -#endif // USE_AUTOCONF - &be_native_module(tapp), - &be_native_module(gpio), -#ifdef USE_DISPLAY - &be_native_module(display), -#endif // USE_DISPLAY -#ifdef USE_LIGHT - &be_native_module(light), -#endif -#if defined(USE_EMULATION) && defined(USE_EMULATION_HUE) - &be_native_module(hue_ntv), - &be_native_module(hue_bridge), -#endif - - &be_native_module(uuid), -#ifdef USE_UNISHOX_COMPRESSION - &be_native_module(unishox), -#endif // USE_UNISHOX_COMPRESSION - -#ifdef USE_WS2812 - &be_native_module(animate), -#endif // USE_WS2812 - -#ifdef USE_LVGL - &be_native_module(lv), - &be_native_module(lv_extra), - &be_native_module(lv_tasmota), -#ifdef USE_LVGL_HASPMOTA - &be_native_module(haspmota), -#endif // USE_LVGL_HASPMOTA -#endif // USE_LVGL -#ifdef USE_ENERGY_SENSOR - &be_native_module(energy), -#endif // USE_ENERGY_SENSOR -#ifdef USE_WEBSERVER - &be_native_module(webserver), -#endif // USE_WEBSERVER -#ifdef USE_ZIGBEE - &be_native_module(zigbee), - &be_native_module(matter_zigbee), -#endif // USE_ZIGBEE - &be_native_module(flash), - &be_native_module(partition_core), - &be_native_module(crc), - &be_native_module(crypto), -#if defined(USE_BERRY_ULP) && ((CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)) - &be_native_module(ULP), -#endif // USE_BERRY_ULP -#if defined(USE_BERRY_TF_LITE) - &be_native_module(TFL), -#endif //USE_BERRY_TF_LITE -#if defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32) - &be_native_module(MI32), - &be_native_module(BLE), -#endif //USE_MI_ESP32 -#ifdef USE_BERRY_CAM - &be_native_module(cam), -#endif -#ifdef USE_DISCOVERY - &be_native_module(mdns), -#endif // USE_DISCOVERY -#ifdef USE_MATTER_DEVICE - &be_native_module(matter), -#endif // USE_MATTER_DEVICE -#endif // TASMOTA - CUSTOM_NATIVE_MODULES - /* user-defined modules register end */ - NULL /* do not remove */ -}; - -be_extern_native_class(dyn); -be_extern_native_class(tasmota); -be_extern_native_class(Trigger); -be_extern_native_class(Driver); -be_extern_native_class(ctypes_bytes); -be_extern_native_class(ctypes_bytes_dyn); -be_extern_native_class(serial); -be_extern_native_class(ccronexpr); -be_extern_native_class(tasmota_log_reader); -be_extern_native_class(light_state); -be_extern_native_class(Wire); -be_extern_native_class(I2C_Driver); -be_extern_native_class(AXP192); -be_extern_native_class(AXP202); -be_extern_native_class(OneWire); -be_extern_native_class(Leds_ntv); -be_extern_native_class(Leds); -be_extern_native_class(AudioGenerator); -be_extern_native_class(AudioFileSource); -be_extern_native_class(AudioOutputI2S); -be_extern_native_class(AudioGeneratorWAV); -be_extern_native_class(AudioGeneratorMP3); -be_extern_native_class(AudioFileSourceFS); -be_extern_native_class(AudioOpusDecoder); -be_extern_native_class(AudioInputI2S); -be_extern_native_class(md5); -be_extern_native_class(udp); -be_extern_native_class(webclient); -be_extern_native_class(tcpclient); -be_extern_native_class(tcpclientasync); -be_extern_native_class(webserver_async); -be_extern_native_class(tcpserver); -be_extern_native_class(energy_struct); -// LVGL core classes -be_extern_native_class(lv_color); -be_extern_native_class(lv_font); -be_extern_native_class(LVGL_glob); -// LVGL custom classes -be_extern_native_class(lv_signal_bars); -be_extern_native_class(lv_wifi_bars); -be_extern_native_class(lv_wifi_bars_icon); -be_extern_native_class(lv_signal_arcs); -be_extern_native_class(lv_wifi_arcs); -be_extern_native_class(lv_wifi_arcs_icon); -be_extern_native_class(lv_clock); -be_extern_native_class(lv_clock_icon); - -be_extern_native_class(int64); - -#ifdef USE_BERRY_IMAGE -be_extern_native_class(img); -#endif // USE_BERRY_IMAGE - -BERRY_LOCAL bclass_array be_class_table = { -#ifdef TASMOTA - /* first list are direct classes */ - &be_native_class(dyn), - &be_native_class(tasmota), - &be_native_class(Trigger), - &be_native_class(Driver), - &be_native_class(serial), - &be_native_class(ccronexpr), - &be_native_class(ctypes_bytes), - &be_native_class(ctypes_bytes_dyn), - &be_native_class(tasmota_log_reader), -#ifdef USE_LIGHT - &be_native_class(light_state), -#endif -#if defined(USE_ONEWIRE) || defined(USE_DS18x20) - &be_native_class(OneWire), -#endif -#ifdef USE_I2C - &be_native_class(Wire), - &be_native_class(I2C_Driver), - &be_native_class(AXP192), - &be_native_class(AXP202), -#endif // USE_I2C - &be_native_class(md5), -#ifdef USE_WEBCLIENT - &be_native_class(udp), - &be_native_class(webclient), - &be_native_class(tcpclient), - &be_native_class(tcpclientasync), -#ifdef USE_BERRY_DEBUG - &be_native_class(webserver_async), // include only when USE_BERRY_DEBUG is enabled -#endif // USE_BERRY_DEBUG -#endif // USE_WEBCLIENT -#ifdef USE_BERRY_TCPSERVER - &be_native_class(tcpserver), -#endif // USE_BERRY_TCPSERVER -#ifdef USE_WS2812 - &be_native_class(Leds_ntv), - &be_native_class(Leds), -#endif // USE_WS2812 -#ifdef USE_ENERGY_SENSOR - &be_native_class(energy_struct), -#endif // USE_ENERGY_SENSOR - -#ifdef USE_LVGL - &be_native_class(LVGL_glob), - - &be_native_class(lv_signal_bars), - &be_native_class(lv_wifi_bars), - &be_native_class(lv_wifi_bars_icon), - &be_native_class(lv_signal_arcs), - &be_native_class(lv_wifi_arcs), - &be_native_class(lv_wifi_arcs_icon), - &be_native_class(lv_clock), - &be_native_class(lv_clock_icon), -#endif // USE_LVGL - -#ifdef USE_BERRY_IMAGE - &be_native_class(img), -#endif // USE_BERRY_IMAGE - -#if defined(USE_I2S_AUDIO_BERRY) && (ESP_IDF_VERSION_MAJOR >= 5) - &be_native_class(AudioGenerator), - &be_native_class(AudioFileSource), - &be_native_class(AudioOutputI2S), - &be_native_class(AudioGeneratorWAV), - &be_native_class(AudioGeneratorMP3), -#ifdef USE_UFILESYS - &be_native_class(AudioFileSourceFS), -#endif // USE_UFILESYS - &be_native_class(AudioOpusDecoder), - &be_native_class(AudioInputI2S), -#endif // defined(USE_I2S_AUDIO_BERRY) && (ESP_IDF_VERSION_MAJOR >= 5) -#endif // TASMOTA - -#if defined(USE_BERRY_INT64) || defined(USE_MATTER_DEVICE) - &be_native_class(int64), -#endif - CUSTOM_NATIVE_CLASSES - NULL, /* do not remove */ -}; - -extern void be_load_ctypes_energy_definitions_lib(bvm *vm); - -/* this code loads the native class definitions */ -BERRY_API void be_load_custom_libs(bvm *vm) -{ - (void)vm; /* prevent a compiler warning */ - - /* add here custom libs */ -#if !BE_USE_PRECOMPILED_OBJECT - /* be_load_xxxlib(vm); */ -#endif -} diff --git a/lib/libesp32/Berry/default/berry_conf.h b/lib/libesp32/Berry/default/berry_conf.h deleted file mode 100644 index 13200f530993..000000000000 --- a/lib/libesp32/Berry/default/berry_conf.h +++ /dev/null @@ -1,323 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BERRY_CONF_H -#define BERRY_CONF_H - -#include - -#ifdef COMPILE_BERRY_LIB - #include "my_user_config.h" - #include "include/tasmota_configurations.h" -#endif - -/* Macro: BE_DEBUG - * Berry interpreter debug switch. - * Default: 0 - **/ -#ifndef BE_DEBUG -#define BE_DEBUG 0 -#endif - -/* Macro: BE_LONGLONG_INT - * Select integer length. - * If the value is 0, use an integer of type int, use a long - * integer type when the value is 1, and use a long long integer - * type when the value is 2. - * Default: 2 - */ -#ifdef TASMOTA -#define BE_INTGER_TYPE 1 // use long int = uint32_t -#else -#define BE_INTGER_TYPE 0 -#endif - -/* Macro: BE_USE_SINGLE_FLOAT - * Select floating point precision. - * Use double-precision floating-point numbers when the value - * is 0 (default), otherwise use single-precision floating-point - * numbers. - * Default: 0 - **/ -#define BE_USE_SINGLE_FLOAT 1 // use `float` not `double` - -/* Macro: BE_BYTES_MAX_SIZE - * Maximum size in bytes of a `bytes()` object. - * Putting too much pressure on the memory allocator can do - * harm, so we limit the maximum size. - * Default: 32kb - **/ -#define BE_BYTES_MAX_SIZE (32*1024) /* 32 kb default value */ - -/* Macro: BE_USE_PRECOMPILED_OBJECT - * Use precompiled objects to avoid creating these objects at - * runtime. Enable this macro can greatly optimize RAM usage. - * Default: 1 - **/ -#define BE_USE_PRECOMPILED_OBJECT 1 - -/* Macro: BE_DEBUG_SOURCE_FILE - * Indicate if each function remembers its source file name - * 0: do not keep the file name (saves 4 bytes per function) - * 1: keep the source file name - * Default: 1 - **/ -#define BE_DEBUG_SOURCE_FILE 0 - -/* Macro: BE_DEBUG_RUNTIME_INFO - * Set runtime error debugging information. - * 0: unable to output source file and line number at runtime. - * 1: output source file and line number information at runtime. - * 2: the information use uint16_t type (save space). - * Default: 1 - **/ -#define BE_DEBUG_RUNTIME_INFO 0 - -/* Macro: BE_DEBUG_VAR_INFO - * Set variable debugging tracking information. - * 0: disable variable debugging tracking information at runtime. - * 1: enable variable debugging tracking information at runtime. - * Default: 1 - **/ -#define BE_DEBUG_VAR_INFO 0 - -/* Macro: BE_USE_PERF_COUNTERS - * Use the obshook function to report low-level actions. - * Default: 0 - **/ -#define BE_USE_PERF_COUNTERS 1 - -/* Macro: BE_VM_OBSERVABILITY_SAMPLING - * If BE_USE_PERF_COUNTERS == 1 - * then the observability hook is called regularly in the VM loop - * allowing to stop infinite loops or too-long running code. - * The value is a power of 2. - * Default: 20 - which translates to 2^20 or ~1 million instructions - **/ -#define BE_VM_OBSERVABILITY_SAMPLING 20 - -/* Macro: BE_STACK_TOTAL_MAX - * Set the maximum total stack size. - * Default: 20000 - **/ -#define BE_STACK_TOTAL_MAX 8000 - -/* Macro: BE_STACK_FREE_MIN - * Set the minimum free count of the stack. The stack idles will - * be checked when a function is called, and the stack will be - * expanded if the number of free is less than BE_STACK_FREE_MIN. - * Default: 10 - **/ -#define BE_STACK_FREE_MIN 20 - -/* Macro: BE_STACK_START - * Set the starting size of the stack at VM creation. - * Default: 50 - **/ -#define BE_STACK_START 100 - -/* Macro: BE_CONST_SEARCH_SIZE - * Constants in function are limited to 255. However the compiler - * will look for a maximum of pre-existing constants to avoid - * performance degradation. This may cause the number of constants - * to be higher than required. - * Increase is you need to solidify functions. - * Default: 50 - **/ -#define BE_CONST_SEARCH_SIZE 150 - -/* Macro: BE_STACK_FREE_MIN - * The short string will hold the hash value when the value is - * true. It may be faster but requires more RAM. - * Default: 0 - **/ -#define BE_USE_STR_HASH_CACHE 0 - -/* Macro: BE_USE_FILE_SYSTEM - * The file system interface will be used when this macro is true - * or when using the OS module. Otherwise the file system interface - * will not be used. - * Default: 0 - **/ -#ifdef TASMOTA -#define BE_USE_FILE_SYSTEM 0 -#else -#define BE_USE_FILE_SYSTEM 1 -#endif - -/* Macro: BE_USE_SCRIPT_COMPILER - * Enable compiler when BE_USE_SCRIPT_COMPILER is not 0, otherwise - * disable the compiler. - * Default: 1 - **/ -#define BE_USE_SCRIPT_COMPILER 1 - -/* Macro: BE_USE_BYTECODE_SAVER - * Enable save bytecode to file when BE_USE_BYTECODE_SAVER is not 0, - * otherwise disable the feature. - * Default: 1 - **/ -#define BE_USE_BYTECODE_SAVER 1 - -/* Macro: BE_USE_BYTECODE_LOADER - * Enable load bytecode from file when BE_USE_BYTECODE_LOADER is not 0, - * otherwise disable the feature. - * Default: 1 - **/ -#define BE_USE_BYTECODE_LOADER 1 - -/* Macro: BE_USE_SHARED_LIB - * Enable shared library when BE_USE_SHARED_LIB is not 0, - * otherwise disable the feature. - * Default: 1 - **/ -#define BE_USE_SHARED_LIB 0 - -/* Macro: BE_USE_OVERLOAD_HASH - * Allows instances to overload hash methods for use in the - * built-in Map class. Disable this feature to crop the code - * size. - * Default: 1 - **/ -#define BE_USE_OVERLOAD_HASH 1 - -/* Macro: BE_USE_DEBUG_HOOK - * Berry debug hook switch. - * Default: 0 - **/ -#define BE_USE_DEBUG_HOOK 0 - -/* Macro: BE_USE_DEBUG_GC - * Enable GC debug mode. This causes an actual gc after each - * allocation. It's much slower and should not be used - * in production code. - * Default: 0 - **/ -#define BE_USE_DEBUG_GC 0 - -/* Macro: BE_USE_DEBUG_STACK - * Enable Stack Resize debug mode. At each function call - * the stack is reallocated at a different memory location - * and the previous location is cleared with toxic data. - * Default: 0 - **/ -#define BE_USE_DEBUG_STACK 0 - -/* Macro: BE_USE_MEM_ALIGNED - * Some embedded processors have special memory areas - * with read/write constraints of being aligned to 32 bits boundaries. - * This options tries to move such memory areas to this region. - * Default: 0 - **/ -#ifdef TASMOTA -#define BE_USE_MEM_ALIGNED 1 -#else -#define BE_USE_MEM_ALIGNED 0 -#endif - -/* Macro: BE_USE_XXX_MODULE - * These macros control whether the related module is compiled. - * When they are true, they will enable related modules. At this - * point you can use the import statement to import the module. - * They will not compile related modules when they are false. - **/ - -#ifdef TASMOTA - #define BE_USE_STRING_MODULE 1 - #define BE_USE_JSON_MODULE 1 - #define BE_USE_MATH_MODULE 1 - #define BE_USE_TIME_MODULE 0 - #define BE_USE_OS_MODULE 0 - #define BE_USE_GLOBAL_MODULE 1 - #define BE_USE_SYS_MODULE 1 - #define BE_USE_DEBUG_MODULE 0 - #define BE_USE_GC_MODULE 1 - #define BE_USE_SOLIDIFY_MODULE 0 - #define BE_USE_INTROSPECT_MODULE 1 - #define BE_USE_STRICT_MODULE 1 -#else - #define BE_USE_STRING_MODULE 1 - #define BE_USE_JSON_MODULE 1 - #define BE_USE_MATH_MODULE 1 - #define BE_USE_TIME_MODULE 1 - #define BE_USE_OS_MODULE 1 - #define BE_USE_GLOBAL_MODULE 1 - #define BE_USE_SYS_MODULE 1 - #define BE_USE_DEBUG_MODULE 1 - #define BE_USE_GC_MODULE 1 - #define BE_USE_SOLIDIFY_MODULE 1 - #define BE_USE_INTROSPECT_MODULE 1 - #define BE_USE_STRICT_MODULE 1 -#endif - -#if defined(USE_BERRY_DEBUG) || !defined(TASMOTA) - #undef BE_USE_DEBUG_MODULE - #undef BE_USE_SOLIDIFY_MODULE - #define BE_USE_DEBUG_MODULE 1 - #define BE_USE_SOLIDIFY_MODULE 1 -#endif // USE_BERRY_DEBUG - -/* Macro: BE_EXPLICIT_XXX - * If these macros are defined, the corresponding function will - * use the version defined by these macros. These macro definitions - * are not required. - * The default is to use the functions in the standard library. - **/ -#ifdef __cplusplus -extern "C" { -#endif - extern void *berry_malloc(size_t size); - extern void berry_free(void *ptr); - extern void *berry_realloc(void *ptr, size_t size); - extern void *berry_malloc32(size_t size); -#ifdef __cplusplus -} -#endif -#ifdef USE_BERRY_PSRAM - #define BE_EXPLICIT_MALLOC berry_malloc - #define BE_EXPLICIT_FREE berry_free - #define BE_EXPLICIT_REALLOC berry_realloc -#else - #define BE_EXPLICIT_MALLOC malloc - #define BE_EXPLICIT_FREE free - #define BE_EXPLICIT_REALLOC realloc -#endif // USE_BERRY_PSRAM - -#define BE_EXPLICIT_ABORT abort -#define BE_EXPLICIT_EXIT exit -// #define BE_EXPLICIT_MALLOC malloc -// #define BE_EXPLICIT_FREE free -// #define BE_EXPLICIT_REALLOC realloc - -/* Macro: be_assert - * Berry debug assertion. Only enabled when BE_DEBUG is active. - * Default: use the assert() function of the standard library. - **/ -#define be_assert(expr) assert(expr) - -/* Tasmota debug specific */ -#ifdef USE_BERRY_DEBUG - #undef BE_DEBUG_RUNTIME_INFO - #define BE_DEBUG_RUNTIME_INFO 1 /* record line information in 32 bits to be places in IRAM */ - #undef BE_DEBUG - #define BE_DEBUG 1 - #undef be_assert - #define be_assert(expr) \ - ((expr) \ - ? (0) \ - : serial_debug("BRY: ASSERT '%s', %s - %i\n", #expr, __FILE__, __LINE__)) - #ifdef USE_LVGL - #undef BE_STACK_START - #define BE_STACK_START 200 - #endif // USE_LVGL - #ifdef USE_MATTER_DEVICE - #undef BE_STACK_START - #define BE_STACK_START 256 - #endif // USE_MATTER_DEVICE -#endif // USE_BERRY_DEBUG - -#endif diff --git a/lib/libesp32/Berry/examples/anon_func.be b/lib/libesp32/Berry/examples/anon_func.be deleted file mode 100644 index 78854ce64a37..000000000000 --- a/lib/libesp32/Berry/examples/anon_func.be +++ /dev/null @@ -1,20 +0,0 @@ -# anonymous function and closure -def count(x) - var arr = [] - for i : 0 .. x - arr.push( - def (n) # loop variable cannot be used directly as free variable - return def () - return n * n - end - end (i) # define and call anonymous function - ) - end - return arr -end - -for xx : count(6) - print(xx()) # 0, 1, 4 ... n * n -end - -return count diff --git a/lib/libesp32/Berry/examples/bigloop.be b/lib/libesp32/Berry/examples/bigloop.be deleted file mode 100644 index a3a77768b232..000000000000 --- a/lib/libesp32/Berry/examples/bigloop.be +++ /dev/null @@ -1,15 +0,0 @@ -import time - -c = time.clock() -do - i = 0 - while i < 100000000 - i += 1 - end -end -print('while iteration 100000000 times', time.clock() - c, 's') - -c = time.clock() -for i : 1 .. 100000000 -end -print('for iteration 100000000 times', time.clock() - c, 's') diff --git a/lib/libesp32/Berry/examples/bintree.be b/lib/libesp32/Berry/examples/bintree.be deleted file mode 100644 index 81936f8a0306..000000000000 --- a/lib/libesp32/Berry/examples/bintree.be +++ /dev/null @@ -1,60 +0,0 @@ -# Reference from https://github.com/BerryMathDevelopmentTeam/BerryMath/blob/master/testscript/BinaryTree.bm - -class node - var v, l, r - def init(v, l, r) - self.v = v - self.l = l - self.r = r - end - def insert(v) - if v < self.v - if self.l - self.l.insert(v) - else - self.l = node(v) - end - else - if self.r - self.r.insert(v) - else - self.r = node (v) - end - end - end - def sort(l) - if (self.l) self.l.sort(l) end - l.push(self.v) - if (self.r) self.r.sort(l) end - end -end - -class btree - var root - def insert(v) - if self.root - self.root.insert(v) - else - self.root = node(v) - end - end - def sort() - var l = [] - if self.root - self.root.sort(l) - end - return l - end -end - -var tree = btree() -tree.insert(-100) -tree.insert(5); -tree.insert(3); -tree.insert(9); -tree.insert(10); -tree.insert(10000000); -tree.insert(1); -tree.insert(-1); -tree.insert(-10); -print(tree.sort()); diff --git a/lib/libesp32/Berry/examples/calcpi.be b/lib/libesp32/Berry/examples/calcpi.be deleted file mode 100644 index 053f878753de..000000000000 --- a/lib/libesp32/Berry/examples/calcpi.be +++ /dev/null @@ -1,16 +0,0 @@ -def cpi(n) - i = 2 - pi = 3 - while i <= n - term = 4.0 / (i * (i + 1) * (i + 2)) - if i % 4 - pi = pi + term - else - pi = pi - term - end - i = i + 2 - end - return pi -end - -print("pi =", cpi(100)) diff --git a/lib/libesp32/Berry/examples/exception.be b/lib/libesp32/Berry/examples/exception.be deleted file mode 100644 index 3a3098dcefc5..000000000000 --- a/lib/libesp32/Berry/examples/exception.be +++ /dev/null @@ -1,12 +0,0 @@ -import debug - -def test_func() - try - compile('def +() end')() - except .. as e, v - print('catch execption:', str(e) + ' >>>\n ' + str(v)) - debug.traceback() - end -end - -test_func() diff --git a/lib/libesp32/Berry/examples/fib_rec.be b/lib/libesp32/Berry/examples/fib_rec.be deleted file mode 100644 index 31ed3817bfae..000000000000 --- a/lib/libesp32/Berry/examples/fib_rec.be +++ /dev/null @@ -1,12 +0,0 @@ -import time - -def fib(x) - if x <= 2 - return 1 - end - return fib(x - 1) + fib(x - 2) -end - -c = time.clock() -print("fib:", fib(38)) # minimum stack size: 78!! -print("time:", time.clock() - c, 's') diff --git a/lib/libesp32/Berry/examples/guess_number.be b/lib/libesp32/Berry/examples/guess_number.be deleted file mode 100644 index 6cbd07e7c0db..000000000000 --- a/lib/libesp32/Berry/examples/guess_number.be +++ /dev/null @@ -1,26 +0,0 @@ -import time -import math - -math.srand(time.time()) -res = math.rand() % 100 -max_test = 7 -test = -1 -idx = 1 -print('Guess a number between 0 and 99. You have', max_test, 'chances.') -while test != res && idx <= max_test - test = number(input(str(idx) + ': enter the number you guessed: ')) - if type(test) != 'int' - print('This is not an integer. Continue!') - continue - elif test > res - print('This number is too large.') - elif test < res - print('This number is too small.') - end - idx = idx + 1 -end -if test == res - print('You win!') -else - print('You failed, the correct answer is', res) -end diff --git a/lib/libesp32/Berry/examples/json.be b/lib/libesp32/Berry/examples/json.be deleted file mode 100644 index d98dff8bb4f7..000000000000 --- a/lib/libesp32/Berry/examples/json.be +++ /dev/null @@ -1,4 +0,0 @@ -import json -print(json.load('{"key": "value"}')) -print(json.dump({'test key': nil})) -print(json.dump({'key1': nil, 45: true}, 'format')) diff --git a/lib/libesp32/Berry/examples/lambda.be b/lib/libesp32/Berry/examples/lambda.be deleted file mode 100644 index 1d0b709bb2ee..000000000000 --- a/lib/libesp32/Berry/examples/lambda.be +++ /dev/null @@ -1,8 +0,0 @@ -# simple lambda example -print((/a b c-> a * b + c)(2, 3, 4)) - -# Y-Combinator and factorial functions -Y = /f-> (/x-> f(/n-> x(x)(n)))(/x-> f(/n-> x(x)(n))) -F = /f-> /x-> x ? f(x - 1) * x : 1 -fact = Y(F) -print('fact(10) == ' .. fact(10)) diff --git a/lib/libesp32/Berry/examples/listdir.be b/lib/libesp32/Berry/examples/listdir.be deleted file mode 100644 index 2dd880118fb7..000000000000 --- a/lib/libesp32/Berry/examples/listdir.be +++ /dev/null @@ -1,16 +0,0 @@ -import os - -def scandir(path) - print('path: ' + path) - for name : os.listdir(path) - var fullname = os.path.join(path, name) - if os.path.isfile(fullname) - print('file: ' + fullname) - else - print('path: ' + fullname) - scandir(fullname) - end - end -end - -scandir('.') diff --git a/lib/libesp32/Berry/examples/qsort.be b/lib/libesp32/Berry/examples/qsort.be deleted file mode 100644 index b09b65672ee0..000000000000 --- a/lib/libesp32/Berry/examples/qsort.be +++ /dev/null @@ -1,42 +0,0 @@ -def qsort(data) - # do once sort - def once(left, right) - var pivot = data[left] # use the 0th value as the pivot - while left < right # check if sort is complete - # put the value less than the pivot to the left - while left < right && data[right] >= pivot - right -= 1 # skip values greater than pivot - end - data[left] = data[right] - # put the value greater than the pivot on the right - while left < right && data[left] <= pivot - left += 1 # skip values less than pivot - end - data[right] = data[left] - end - # now we have the index of the pivot, store it - data[left] = pivot - return left # return the index of the pivot - end - # recursive quick sort algorithm - def _sort(left, right) - if left < right # executed when the array is not empty - var index = once(left, right) # get index of pivot for divide and conquer - _sort(left, index - 1) # sort the data on the left - _sort(index + 1, right) # sort the data on the right - end - end - # start quick sort - _sort(0, data.size() - 1) - return data -end - -import time, math -math.srand(time.time()) # sse system time as a random seed -data = [] -# put 20 random numbers into the array -for i : 1 .. 20 - data.push(math.rand() % 100) -end -# sort and print -print(qsort(data)) diff --git a/lib/libesp32/Berry/examples/repl.be b/lib/libesp32/Berry/examples/repl.be deleted file mode 100644 index aac26b0a1b2f..000000000000 --- a/lib/libesp32/Berry/examples/repl.be +++ /dev/null @@ -1,61 +0,0 @@ -do - def ismult(msg) - import string - return string.split(msg, -5)[1] == '\'EOS\'' - end - - def multline(src, msg) - if !ismult(msg) - print('syntax_error: ' + msg) - return - end - while true - try - src += '\n' + input('>> ') - return compile(src) - except 'syntax_error' as e, m - if !ismult(m) - print('syntax_error: ' + m) - return - end - end - end - end - - def parse() - var fun, src = input('> ') - try - fun = compile('return (' + src + ')') - except 'syntax_error' as e, m - try - fun = compile(src) - except 'syntax_error' as e, m - fun = multline(src, m) - end - end - return fun - end - - def run(fun) - try - var res = fun() - if res print(res) end - except .. as e, m - import debug - print(e .. ': ' .. m) - debug.traceback() - end - end - - def repl() - while true - var fun = parse() - if fun != nil - run(fun) - end - end - end - - print("Berry Berry REPL!") - repl() -end diff --git a/lib/libesp32/Berry/examples/string.be b/lib/libesp32/Berry/examples/string.be deleted file mode 100644 index 299834e21c2d..000000000000 --- a/lib/libesp32/Berry/examples/string.be +++ /dev/null @@ -1,32 +0,0 @@ -s = "This is a long string test. 0123456789 abcdefg ABCDEFG" -print(s) - -a = .5 -print(a) - -import string as s - -print(s.hex(0x45678ABCD, 16)) - -def bin(x, num) - assert(type(x) == 'int', 'the type of \'x\' must be integer') - # test the 'x' bits - var bits = 1 - for i : 0 .. 62 - if x & (1 << 63 - i) - bits = 64 - i - break - end - end - if type(num) == 'int' && num > 0 && num <= 64 - bits = bits < num ? num : bits - end - var result = '' - bits -= 1 - for i : 0 .. bits - result += x & (1 << (bits - i)) ? '1' : '0' - end - return result -end - -print(bin(33)) diff --git a/lib/libesp32/Berry/examples/strmod.be b/lib/libesp32/Berry/examples/strmod.be deleted file mode 100644 index 8660f5b4ec7d..000000000000 --- a/lib/libesp32/Berry/examples/strmod.be +++ /dev/null @@ -1,7 +0,0 @@ -import string - -print(string.format('%.3d', 12)) -print(string.format('%.3f', 12)) -print(string.format('%20.7f', 14.5)) -print(string.format('-- %-40s ---', 'this is a string format test')) -print(string.format('-- %40s ---', 'this is a string format test')) diff --git a/lib/libesp32/Berry/gen.sh b/lib/libesp32/Berry/gen.sh deleted file mode 100755 index e248a977f1d9..000000000000 --- a/lib/libesp32/Berry/gen.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# -# generate all precompiled Berry structures from multiple modules -# -# Included in the Platformio build process with `pio-tools/gen-berry-structures.py -# -rm -Rf ./generate/be_*.h -python3 tools/coc/coc -o generate src default ../berry_tasmota/src ../berry_mapping/src ../berry_int64/src ../../libesp32_lvgl/lv_binding_berry/src ../../libesp32_lvgl/lv_haspmota/src/solidify ../berry_matter/src/solidify ../berry_matter/src ../berry_animate/src/solidify ../berry_animate/src ../../libesp32_lvgl/lv_binding_berry/src/solidify ../../libesp32_lvgl/lv_binding_berry/generate -c default/berry_conf.h diff --git a/lib/libesp32/Berry/library.json b/lib/libesp32/Berry/library.json deleted file mode 100644 index e5b08a1de0d6..000000000000 --- a/lib/libesp32/Berry/library.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name":"Berry", - "description":"Berry scripting language for Tasmota32", - "keywords":"berry, script", - "authors": - { - "name": "Guan Wenliang , ", - "maintainer": true - }, - "repository": - { - "type": "git", - "url": "https://github.com/Skiars/berry" - }, - "version": "7.0", - "license": "MIT License", - "frameworks": "arduino", - "platforms": "espressif32", - "build": { - "includeDir": "generate", - "srcFilter": [ - "+<*.c>", - "+<../default/*.c>", - "+<../default/*.cpp>", - "+<../default/*.hpp>", - "+<../generate/*.h>", - "+<*.cpp>", - "+<*.h>" - ], - "flags": [ "-I$PROJECT_DIR/tasmota", "-DCOMPILE_BERRY_LIB", "-includeesp_idf_version.h" ] - } -} diff --git a/lib/libesp32/Berry/src/be_api.c b/lib/libesp32/Berry/src/be_api.c deleted file mode 100644 index 6ccb65c5accb..000000000000 --- a/lib/libesp32/Berry/src/be_api.c +++ /dev/null @@ -1,1179 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_vm.h" -#include "be_func.h" -#include "be_class.h" -#include "be_string.h" -#include "be_vector.h" -#include "be_var.h" -#include "be_list.h" -#include "be_map.h" -#include "be_parser.h" -#include "be_debug.h" -#include "be_exec.h" -#include "be_strlib.h" -#include "be_module.h" -#include "be_gc.h" -#include - -#define retreg(vm) ((vm)->cf->func) - -struct solidfuncinfo { - const char *name; - bclosure *function; -}; - -static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib) -{ - if (lib) { - while (lib->name) { - bstring *s = be_newstr(vm, lib->name); - if (lib->function) { /* method */ - be_class_native_method_bind(vm, c, s, lib->function); - } else { - be_class_member_bind(vm, c, s, btrue); /* member */ - } - ++lib; - } - if (lib->function == (bntvfunc)BE_CLOSURE) { - /* next section is closures */ - struct solidfuncinfo *slib = (struct solidfuncinfo*)++lib; - while (slib->name) { - if (slib->function) { /* method */ - bstring *s = be_newstr(vm, slib->name); - be_class_closure_method_bind(vm, c, s, slib->function); - } - ++slib; - } - } - be_map_compact(vm, c->members); /* clear space */ - } -} - -static bclass* class_auto_make(bvm *vm, bstring *name, const bnfuncinfo *lib) -{ - bvalue key, *res; - var_setobj(&key, BE_COMPTR, (void*)lib); - if (vm->ntvclass == NULL) { - vm->ntvclass = be_map_new(vm); - } - res = be_map_find(vm, vm->ntvclass, &key); - if (res == NULL || !var_isclass(res)) { - bclass *c; - /* insert class to native class table */ - res = be_map_insert(vm, vm->ntvclass, &key, NULL); - var_setnil(res); /* must be initialized to ensure correct GC */ - c = be_newclass(vm, name, NULL); - var_setclass(res, c); - class_init(vm, c, lib); /* bind members */ - return c; - } - return var_toobj(res); -} - -BERRY_API void be_regfunc(bvm *vm, const char *name, bntvfunc f) -{ - bvalue *var; - bstring *s = be_newstr(vm, name); -#if !BE_USE_PRECOMPILED_OBJECT - int idx = be_builtin_find(vm, s); - be_assert(idx == -1); - if (idx == -1) { /* new function */ - idx = be_builtin_new(vm, s); -#else - int idx = be_global_find(vm, s); - be_assert(idx < be_builtin_count(vm)); - if (idx < be_builtin_count(vm)) { /* new function */ - idx = be_global_new(vm, s); -#endif - var = be_global_var(vm, idx); - var_setntvfunc(var, f); - } /* error case, do nothing */ -} - -BERRY_API void be_regclass(bvm *vm, const char *name, const bnfuncinfo *lib) -{ - bvalue *var; - bstring *s = be_newstr(vm, name); -#if !BE_USE_PRECOMPILED_OBJECT - int idx = be_builtin_find(vm, s); - be_assert(idx == -1); - if (idx == -1) { /* new function */ - idx = be_builtin_new(vm, s); -#else - int idx = be_global_find(vm, s); - be_assert(idx < be_builtin_count(vm)); - if (idx < be_builtin_count(vm)) { /* new function */ - idx = be_global_new(vm, s); -#endif - var = be_global_var(vm, idx); - var_setclass(var, class_auto_make(vm, s, lib)); - } /* error case, do nothing */ -} - -BERRY_API int be_top(bvm *vm) -{ - return cast_int(vm->top - vm->reg); -} - -BERRY_API void be_pop(bvm *vm, int n) -{ - be_assert(n <= vm->top - vm->reg); - be_stackpop(vm, n); -} - -BERRY_API int be_absindex(bvm *vm, int index) -{ - if (index > 0) { - return index; - } - be_assert(vm->reg <= vm->top + index); - return cast_int(vm->top + index - vm->reg + 1); -} - -BERRY_API bbool be_isnil(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isnil(v); -} - -BERRY_API bbool be_isbool(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isbool(v); -} - -BERRY_API bbool be_isint(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isint(v); -} - -BERRY_API bbool be_isreal(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isreal(v); -} - -BERRY_API bbool be_isnumber(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isnumber(v); -} - -BERRY_API bbool be_isstring(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isstr(v); -} - -BERRY_API bbool be_isclosure(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isclosure(v); -} - -BERRY_API bbool be_isntvclos(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isntvclos(v); -} - -BERRY_API bbool be_isfunction(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isfunction(v); -} - -BERRY_API bbool be_isproto(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isproto(v); -} - -BERRY_API bbool be_isclass(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isclass(v); -} - -BERRY_API bbool be_isinstance(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_isinstance(v); -} - -static bbool be_isinstanceofbuiltin(bvm *vm, int rel_index, const char *classname) -{ - bbool ret = bfalse; - int index = be_absindex(vm, rel_index); - if (be_isinstance(vm, index)) { - be_getbuiltin(vm, classname); - if (be_isderived(vm, index)) { - ret = btrue; - } - be_pop(vm, 1); - } - return ret; -} - -BERRY_API bbool be_ismapinstance(bvm *vm, int index) -{ - return be_isinstanceofbuiltin(vm, index, "map"); -} - -BERRY_API bbool be_islistinstance(bvm *vm, int index) -{ - return be_isinstanceofbuiltin(vm, index, "list"); -} - - -BERRY_API bbool be_ismodule(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_ismodule(v); -} - -BERRY_API bbool be_islist(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_islist(v); -} - -BERRY_API bbool be_ismap(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_ismap(v); -} - -BERRY_API bbool be_iscomptr(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_istype(v, BE_COMPTR); -} - -BERRY_API bbool be_iscomobj(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_istype(v, BE_COMOBJ); -} - -BERRY_API bint be_toint(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_toint(v); -} - -BERRY_API breal be_toreal(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_isreal(v)) { - return var_toreal(v); - } - if (var_isint(v)) { - return cast(breal, var_toint(v)); - } - return cast(breal, 0.0); -} - -BERRY_API int be_toindex(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return var_toidx(v); -} - -BERRY_API bbool be_tobool(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return be_value2bool(vm, v); -} - -BERRY_API const char* be_tostring(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (!var_isstr(v)) { - be_val2str(vm, index); - v = be_indexof(vm, index); - } - return str(var_tostr(v)); -} - -BERRY_API void* be_tocomptr(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_istype(v, BE_COMPTR)) { - return var_toobj(v); - } - if (var_istype(v, BE_COMOBJ)) { - bcommomobj *obj = var_toobj(v); - return obj->data; - } - return NULL; -} - -BERRY_API void be_moveto(bvm *vm, int from, int to) -{ - bvalue *src = be_indexof(vm, from); - bvalue *dst = be_indexof(vm, to); - var_setval(dst, src); -} - -BERRY_API void be_pushnil(bvm *vm) -{ - bvalue *reg = be_incrtop(vm); - var_setnil(reg); -} - -BERRY_API void be_pushbool(bvm *vm, int b) -{ - bvalue *reg = be_incrtop(vm); - var_setbool(reg, b != bfalse); -} - -BERRY_API void be_pushint(bvm *vm, bint i) -{ - bvalue *reg = be_incrtop(vm); - var_setint(reg, i); -} - -BERRY_API void be_pushreal(bvm *vm, breal r) -{ - bvalue *reg = be_incrtop(vm); - var_setreal(reg, r); -} - -BERRY_API void be_pushstring(bvm *vm, const char *str) -{ - /* to create a string and then push the top registor, - * otherwise the GC may crash due to uninitialized values. - **/ - bstring *s = be_newstr(vm, str); - bvalue *reg = be_incrtop(vm); - be_assert(reg < vm->stacktop); - var_setstr(reg, s); -} - -BERRY_API void be_pushnstring(bvm *vm, const char *str, size_t n) -{ - /* to create a string and then push the top registor, - * otherwise the GC may crash due to uninitialized values. - **/ - bstring *s = be_newstrn(vm, str, n); - bvalue *reg = be_incrtop(vm); - var_setstr(reg, s); -} - -BERRY_API const char* be_pushfstring(bvm *vm, const char *format, ...) -{ - const char* s; - va_list arg_ptr; - va_start(arg_ptr, format); - s = be_pushvfstr(vm, format, arg_ptr); - va_end(arg_ptr); - return s; -} - -BERRY_API void* be_pushbuffer(bvm *vm, size_t size) -{ - bstring *s = be_newlongstr(vm, NULL, size); - bvalue *reg = be_incrtop(vm); - var_setstr(reg, s); - return (void*)str(s); -} - -BERRY_API void be_pushvalue(bvm *vm, int index) -{ - bvalue *reg = vm->top; - var_setval(reg, be_indexof(vm, index)); - be_incrtop(vm); -} - -BERRY_API void be_pushclosure(bvm *vm, void *cl) -{ - bvalue *reg = be_incrtop(vm); - bclosure * closure = (bclosure*) cl; - var_setclosure(reg, closure); -} - -BERRY_API void be_pushntvclosure(bvm *vm, bntvfunc f, int nupvals) -{ - /* to create a native closure and then push the top registor, - * otherwise the GC may crash due to uninitialized values. - **/ - bntvclos *cl = be_newntvclosure(vm, f, nupvals); - bvalue *top = be_incrtop(vm); - var_setntvclos(top, cl); -} - -BERRY_API void be_pushntvfunction(bvm *vm, bntvfunc f) -{ - bvalue *top = be_incrtop(vm); - var_setntvfunc(top, f); -} - -BERRY_API void be_pushclass(bvm *vm, const char *name, const bnfuncinfo *lib) -{ - bclass *c; - bstring *s = be_newstr(vm, name); - bvalue *dst = be_incrtop(vm); - var_setstr(dst, s); - c = class_auto_make(vm, s, lib); - var_setclass(vm->top - 1, c); -} - -BERRY_API void be_pushntvclass(bvm *vm, const struct bclass * c) -{ - bvalue *top = be_incrtop(vm); - var_setclass(top, (bclass *) c); -} - -BERRY_API void be_pushcomptr(bvm *vm, void *ptr) -{ - bvalue *top = be_incrtop(vm); - var_setobj(top, BE_COMPTR, ptr); -} - -BERRY_API void be_remove(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - bvalue *top = --vm->top; - while (v < top) { - *v = v[1]; - ++v; - } -} - -BERRY_API void be_strconcat(bvm *vm, int index) -{ - bstring *s; - bvalue *dst = be_indexof(vm, index); - bvalue *src = be_indexof(vm, -1); - be_assert(var_isstr(src) && var_isstr(dst)); - s = be_strcat(vm, var_tostr(dst), var_tostr(src)); - var_setstr(dst, s); -} - -BERRY_API bbool be_setsuper(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - bvalue *top = be_indexof(vm, -1); - if (var_isclass(v) && var_isclass(top)) { - bclass *c = var_toobj(v); - if (!gc_isconst(c)) { - bclass *super = var_toobj(top); - be_class_setsuper(c, super); - return btrue; - } - } - return bfalse; -} - -BERRY_API void be_getsuper(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - bvalue *top = be_incrtop(vm); - if (var_isclass(v)) { - bclass *c = var_toobj(v); - c = be_class_super(c); - if (c) { - var_setclass(top, c); - return; - } - } else if (var_isinstance(v)) { - binstance *o = var_toobj(v); - o = be_instance_super(o); - if (o) { - var_setinstance(top, o); - return; - } - } - var_setnil(top); -} - -static bclass* _getclass(bvalue *v) -{ - if (var_isinstance(v)) { - binstance *ins = var_toobj(v); - return be_instance_class(ins); - } - return var_isclass(v) ? var_toobj(v) : NULL; -} - -BERRY_API bbool be_isderived(bvm *vm, int index) -{ - bclass *sup = _getclass(be_indexof(vm, -1)); - if (sup) { - bclass *c = _getclass(be_indexof(vm, index)); - while (c && c != sup) - c = be_class_super(c); - return c != NULL; - } - return bfalse; -} - -BERRY_API const char *be_typename(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - return be_vtype2str(v); -} - -BERRY_API const char *be_classname(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_isclass(v)) { - bclass *c = var_toobj(v); - return str(be_class_name(c)); - } - if (var_isinstance(v)) { - binstance *i = var_toobj(v); - return str(be_instance_name(i)); - } - return NULL; -} - -BERRY_API bbool be_classof(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_isinstance(v)) { - bvalue *top = be_incrtop(vm); - binstance *ins = var_toobj(v); - var_setclass(top, be_instance_class(ins)); - return btrue; - } - return bfalse; -} - -BERRY_API int be_strlen(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_isstr(v)) { - return str_len(var_tostr(v)); - } - return 0; -} - -BERRY_API void be_newlist(bvm *vm) -{ - blist *list = be_list_new(vm); - bvalue *top = be_incrtop(vm); - var_setlist(top, list); -} - -BERRY_API void be_newmap(bvm *vm) -{ - bmap *map = be_map_new(vm); - bvalue *top = be_incrtop(vm); - var_setobj(top, BE_MAP, map); -} - -BERRY_API void be_newmodule(bvm *vm) -{ - bmodule *mod = be_module_new(vm); - bvalue *top = be_incrtop(vm); - var_setobj(top, BE_MODULE, mod); -} - -BERRY_API void be_newobject(bvm *vm, const char *name) -{ - be_getbuiltin(vm, name); - be_call(vm, 0); - be_getmember(vm, -1, ".p"); -} - -BERRY_API bbool be_setname(bvm *vm, int index, const char *name) -{ - bvalue *v = be_indexof(vm, index); - if (var_ismodule(v)) { - bmodule *module = var_toobj(v); - return be_module_setname(module, be_newstr(vm, name)); - } - return bfalse; -} - -BERRY_API bbool be_getglobal(bvm *vm, const char *name) -{ - int idx = be_global_find(vm, be_newstr(vm, name)); - bvalue *top = be_incrtop(vm); - if (idx > -1) { - *top = *be_global_var(vm, idx); - return btrue; - } - var_setnil(top); - return bfalse; -} - -BERRY_API void be_setglobal(bvm *vm, const char *name) -{ - int idx; - bstring *s = be_newstr(vm, name); - bvalue *v = be_incrtop(vm); - var_setstr(v, s); - idx = be_global_new(vm, s); - v = be_global_var(vm, idx); - *v = *be_indexof(vm, -2); - be_stackpop(vm, 1); -} - -BERRY_API bbool be_getbuiltin(bvm *vm, const char *name) -{ - int idx = be_builtin_find(vm, be_newstr(vm, name)); - bvalue *top = be_incrtop(vm); - if (idx > -1) { - *top = *be_global_var(vm, idx); - return btrue; - } - var_setnil(top); - return bfalse; -} - -BERRY_API bbool be_setmember(bvm *vm, int index, const char *k) -{ - bvalue *o = be_indexof(vm, index); - bvalue *v = be_indexof(vm, -1); - if (var_isinstance(o)) { - bstring *key = be_newstr(vm, k); - binstance *obj = var_toobj(o); - return be_instance_setmember(vm, obj, key, v); - } else if (var_ismodule(o)) { - bstring *key = be_newstr(vm, k); - bmodule *mod = var_toobj(o); - return be_module_setmember(vm, mod, key, v); - } else if (var_isclass(o)) { - bstring *key = be_newstr(vm, k); - bclass *cl = var_toobj(o); - return be_class_setmember(vm, cl, key, v); - } - return bfalse; -} - -BERRY_API bbool be_copy(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - bvalue *top = be_incrtop(vm); - if (var_type(v) == BE_LIST) { - blist *list = be_list_copy(vm, var_toobj(v)); - var_setlist(top, list) - return btrue; - } - var_setnil(top); - return bfalse; -} - -/* `onlyins` limits the search to instance, and discards module. Makes sure getmethod does not return anything for module. */ -/* may return BE_NONE */ -static int ins_member(bvm *vm, int index, const char *k, bbool onlyins) -{ - int type = BE_NIL; - bvalue *o = be_indexof(vm, index); - bvalue *top = be_incrtop(vm); - var_setnil(top); - if (var_isinstance(o)) { - binstance *obj = var_toobj(o); - type = be_instance_member(vm, obj, be_newstr(vm, k), top); - } else if (var_isclass(o) && !onlyins) { - bclass *cl = var_toobj(o); - type = be_class_member(vm, cl, be_newstr(vm, k), top); - } else if (var_ismodule(o) && !onlyins) { - bmodule *module = var_toobj(o); - type = be_module_attr(vm, module, be_newstr(vm, k), top); - } - return type; -} - -BERRY_API bbool be_getmember(bvm *vm, int index, const char *k) -{ - return ins_member(vm, index, k, bfalse) != BE_NONE; -} - -BERRY_API bbool be_getmethod(bvm *vm, int index, const char *k) -{ - return basetype(ins_member(vm, index, k, btrue)) == BE_FUNCTION; -} - -BERRY_API bbool be_getindex(bvm *vm, int index) -{ - bvalue *o = be_indexof(vm, index); - bvalue *k = be_indexof(vm, -1); - bvalue *dst = be_incrtop(vm); - switch (var_type(o)) { - case BE_LIST: - if (var_isint(k)) { - blist *list = cast(blist*, var_toobj(o)); - int idx = var_toidx(k); - bvalue *src = be_list_index(list, idx); - if (src) { - var_setval(dst, src); - return btrue; - } - } - break; - case BE_MAP: - if (!var_isnil(k)) { - bmap *map = cast(bmap*, var_toobj(o)); - bvalue *src = be_map_find(vm, map, k); - if (src) { - var_setval(dst, src); - return btrue; - } - } - break; - default: - break; - } - var_setnil(dst); - return bfalse; -} - -static bvalue* list_setindex(blist *list, bvalue *key) -{ - int idx = var_toidx(key); - if (idx < 0) { - idx = list->count + idx; - } - if (idx < 0 || idx >= list->count) { - return NULL; - } - return be_list_at(list, idx); -} - -BERRY_API bbool be_setindex(bvm *vm, int index) -{ - bvalue *dst = NULL; - bvalue *o = be_indexof(vm, index); - bvalue *k = be_indexof(vm, -2); - bvalue *v = be_indexof(vm, -1); - switch (var_type(o)) { - case BE_LIST: - if (var_isint(k)) { - blist *list = var_toobj(o); - dst = list_setindex(list, k); - } - break; - case BE_MAP: - if (!var_isnil(k)) { - bmap *map = var_toobj(o); - dst = be_map_insert(vm, map, k, NULL); - } - break; - default: - break; - } - if (dst) { - var_setval(dst, v); - return btrue; - } - return bfalse; -} - -BERRY_API void be_getupval(bvm *vm, int index, int pos) -{ - bvalue *f = index ? be_indexof(vm, index) : vm->cf->func; - bvalue *uv, *top = be_incrtop(vm); - be_assert(var_istype(f, BE_NTVCLOS)); - if (var_istype(f, BE_NTVCLOS)) { - bntvclos *nf = var_toobj(f); - be_assert(pos >= 0 && pos < nf->nupvals); - uv = be_ntvclos_upval(nf, pos)->value; - var_setval(top, uv); - } else { - var_setnil(top); - } -} - -BERRY_API bbool be_setupval(bvm *vm, int index, int pos) -{ - bvalue *f = index ? be_indexof(vm, index) : vm->cf->func; - bvalue *uv, *v = be_indexof(vm, -1); - be_assert(var_istype(f, BE_NTVCLOS)); - if (var_istype(f, BE_NTVCLOS)) { - bntvclos *nf = var_toobj(f); - be_assert(pos >= 0 && pos < nf->nupvals); - uv = be_ntvclos_upval(nf, pos)->value; - var_setval(uv, v); - return btrue; - } - return bfalse; -} - -BERRY_API int be_data_size(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_islist(v)) { - blist *list = var_toobj(v); - return be_list_count(list); - } else if (var_ismap(v)) { - bmap *map = cast(bmap*, var_toobj(v)); - return be_map_count(map); - } - return -1; -} - -BERRY_API void be_data_push(bvm *vm, int index) -{ - bvalue *o = be_indexof(vm, index); - bvalue *v = be_indexof(vm, -1); - if (var_islist(o)) { - blist *list = var_toobj(o); - be_list_push(vm, list, v); - } -} - -BERRY_API bbool be_data_insert(bvm *vm, int index) -{ - bvalue *o = be_indexof(vm, index); - bvalue *k = be_indexof(vm, -2); - bvalue *v = be_indexof(vm, -1); - switch (var_type(o)) { - case BE_MAP: - if (!var_isnil(k)) { - bmap *map = cast(bmap*, var_toobj(o)); - bvalue *dst = be_map_find(vm, map, k); - if (dst == NULL) { - return be_map_insert(vm, map, k, v) != NULL; - } - } - break; - case BE_LIST: - if (var_isint(k)) { - blist *list = cast(blist*, var_toobj(o)); - return be_list_insert(vm, list, var_toidx(k), v) != NULL; - } - break; - default: - break; - } - return bfalse; -} - -BERRY_API bbool be_data_remove(bvm *vm, int index) -{ - bvalue *o = be_indexof(vm, index); - bvalue *k = be_indexof(vm, -1); - switch (var_type(o)) { - case BE_MAP: - if (!var_isnil(k)) { - bmap *map = cast(bmap*, var_toobj(o)); - return be_map_remove(vm, map, k); - } - break; - case BE_LIST: - if (var_isint(k)) { - blist *list = cast(blist*, var_toobj(o)); - return be_list_remove(vm, list, var_toidx(k)); - } - break; - default: - break; - } - return bfalse; -} - -BERRY_API bbool be_data_merge(bvm *vm, int index) -{ - bvalue *a = be_indexof(vm, index); - bvalue *b = be_indexof(vm, -1); - if (var_islist(a) && var_islist(b)) { - blist *dst = var_toobj(a), *src = var_toobj(b); - be_list_merge(vm, dst, src); - return btrue; - } - return bfalse; -} - -BERRY_API void be_data_resize(bvm *vm, int index) -{ - bvalue *o = be_indexof(vm, index); - bvalue *v = be_indexof(vm, -1); - if (var_islist(o)) { - blist *list = var_toobj(o); - if (var_isint(v)) { - be_list_resize(vm, list, var_toidx(v)); - } - } -} - -BERRY_API void be_data_reverse(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_type(v) == BE_LIST) { - be_list_reverse(var_toobj(v)); - } -} - -BERRY_API bbool be_pushiter(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - if (var_ismap(v)) { - bvalue *iter = be_incrtop(vm); - var_setobj(iter, BE_COMPTR, NULL); - return btrue; - } else if (var_islist(v)) { - blist *list = var_toobj(v); - bvalue *iter = be_incrtop(vm); - var_setobj(iter, BE_COMPTR, be_list_data(list) - 1); - return btrue; - } - return bfalse; -} - -static int list_next(bvm *vm) -{ - bvalue *iter = be_indexof(vm, -1); - bvalue *next, *dst = be_incrtop(vm); - next = cast(bvalue*, var_toobj(iter)) + 1; - var_setobj(iter, BE_COMPTR, next); - var_setval(dst, next); - return 1; -} - -static bbool list_hasnext(bvm *vm, bvalue *v) -{ - bvalue *next; - bvalue *iter = be_indexof(vm, -1); - blist *obj = var_toobj(v); - next = cast(bvalue*, var_toobj(iter)) + 1; - return next >= be_list_data(obj) && next < be_list_end(obj); -} - -static int map_next(bvm *vm, bvalue *v) -{ - bmapiter iter; - bmapnode *entry; - bvalue *dst = vm->top; - bvalue *itvar = be_indexof(vm, -1); - iter = var_toobj(itvar); - entry = be_map_next(var_toobj(v), &iter); - var_setobj(itvar, BE_COMPTR, iter); - if (entry) { - be_map_key2value(dst, entry); - var_setval(dst + 1, &entry->value); - vm->top += 2; - return 2; - } - return 0; -} - -static bbool map_hasnext(bvm *vm, bvalue *v) -{ - bvalue *node = be_indexof(vm, -1); - bmapiter iter = var_toobj(node); - return be_map_next(var_toobj(v), &iter) != NULL; -} - -BERRY_API int be_iter_next(bvm *vm, int index) -{ - bvalue *o = be_indexof(vm, index); - if (var_islist(o)) { - return list_next(vm); - } else if (var_ismap(o)) { - return map_next(vm, o); - } - return 0; -} - -BERRY_API bbool be_iter_hasnext(bvm *vm, int index) -{ - bvalue *o = be_indexof(vm, index); - if (var_islist(o)) { - return list_hasnext(vm, o); - } else if (var_ismap(o)) { - return map_hasnext(vm, o); - } - return bfalse; -} - -BERRY_API bbool be_refcontains(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - binstance **ref = be_stack_base(&vm->refstack); - binstance **top = be_stack_top(&vm->refstack); - binstance *ins = var_toobj(v); - be_assert(var_isinstance(v)); - if (ref) { - while (ref <= top && *ref != ins) { - ++ref; - } - return ref <= top; - } - return bfalse; -} - -BERRY_API void be_refpush(bvm *vm, int index) -{ - bvalue *v = be_indexof(vm, index); - binstance *ins = var_toobj(v); - be_assert(var_isinstance(v)); - be_stack_push(vm, &vm->refstack, &ins); -} - -BERRY_API void be_refpop(bvm *vm) -{ - be_stack_pop(&vm->refstack); - if (be_stack_isempty(&vm->refstack)) { - be_vector_release(vm, &vm->refstack); - } -} - -BERRY_API int be_returnvalue(bvm *vm) -{ - bvalue *src = vm->top - 1; - bvalue *ret = retreg(vm); - var_setval(ret, src); - return 0; -} - -BERRY_API int be_returnnilvalue(bvm *vm) -{ - bvalue *ret = retreg(vm); - var_setnil(ret); - return 0; -} - -BERRY_API void be_call(bvm *vm, int argc) -{ - bvalue *fval = vm->top - argc - 1; - be_dofunc(vm, fval, argc); -} - -BERRY_API int be_pcall(bvm *vm, int argc) -{ - bvalue *f = vm->top - argc - 1; - return be_protectedcall(vm, f, argc); -} - -#ifdef __GNUC__ -__attribute__((noreturn)) -#endif -BERRY_API void be_raise(bvm *vm, const char *except, const char *msg) -{ - be_pushstring(vm, except); - if (msg) { - be_pushstring(vm, msg); - } else { - be_pushnil(vm); - } - be_pop(vm, 2); - be_save_stacktrace(vm); - be_throw(vm, BE_EXCEPTION); -#ifdef __GNUC__ - __builtin_unreachable(); -#endif -} - -BERRY_API void be_stop_iteration(bvm *vm) -{ - be_raise(vm, "stop_iteration", NULL); -} - -BERRY_API int be_getexcept(bvm *vm, int code) -{ - if (code == BE_EXCEPTION) { - if (be_isstring(vm, -2)) { - const char *except = be_tostring(vm, -2); - if (!strcmp(except, "syntax_error")) { - return BE_SYNTAX_ERROR; - } - if (!strcmp(except, "io_error")) { - return BE_IO_ERROR; - } - } - return BE_EXEC_ERROR; - } - return code; -} - -static int _dvfunc(bvm *vm, bbool esc) -{ - const char* s = esc ? - be_toescape(vm, 1, 'x') : be_tostring(vm, 1); - be_writestring(s); - be_return_nil(vm); -} - -static int _dumpesc(bvm *vm) -{ - return _dvfunc(vm, btrue); -} - -static int _dumpdir(bvm *vm) -{ - return _dvfunc(vm, bfalse); -} - -static int dump_value(bvm *vm, int index, bbool esc) -{ - int res, top = be_top(vm) + 1; - index = be_absindex(vm, index); - be_pushntvfunction(vm, esc ? _dumpesc : _dumpdir); - be_pushvalue(vm, index); - res = be_pcall(vm, 1); /* using index to store result */ - be_remove(vm, top); /* remove '_dumpvalue' function */ - be_remove(vm, top); /* remove the value */ - if (res == BE_EXCEPTION) { - be_dumpexcept(vm); - } - return res; -} - -BERRY_API void be_dumpvalue(bvm *vm, int index) -{ - if (dump_value(vm, index, btrue) == BE_OK) { - be_writenewline(); - } -} - -BERRY_API void be_dumpexcept(bvm *vm) -{ - do { - /* print exception value */ - if (dump_value(vm, -2, bfalse)) break; - be_writestring(": "); - /* print exception argument */ - if (dump_value(vm, -1, bfalse)) break; - be_writenewline(); - /* print stack traceback */ - be_tracestack(vm); - } while (0); - be_pop(vm, 2); /* pop the exception value & argument */ -} - -BERRY_API bbool be_iseq(bvm *vm) -{ - be_assert(vm->reg + 2 <= vm->top); - return be_vm_iseq(vm, vm->top - 2, vm->top - 1); -} - -BERRY_API bbool be_isneq(bvm *vm) -{ - be_assert(vm->reg + 2 <= vm->top); - return be_vm_isneq(vm, vm->top - 2, vm->top - 1); -} - -BERRY_API bbool be_islt(bvm *vm) -{ - be_assert(vm->reg + 2 <= vm->top); - return be_vm_islt(vm, vm->top - 2, vm->top - 1); -} - -BERRY_API bbool be_isle(bvm *vm) -{ - be_assert(vm->reg + 2 <= vm->top); - return be_vm_isle(vm, vm->top - 2, vm->top - 1); -} - -BERRY_API bbool be_isgt(bvm *vm) -{ - be_assert(vm->reg + 2 <= vm->top); - return be_vm_isgt(vm, vm->top - 2, vm->top - 1); -} - -BERRY_API bbool be_isge(bvm *vm) -{ - be_assert(vm->reg + 2 <= vm->top); - return be_vm_isge(vm, vm->top - 2, vm->top - 1); -} diff --git a/lib/libesp32/Berry/src/be_baselib.c b/lib/libesp32/Berry/src/be_baselib.c deleted file mode 100644 index 3cc2e9f2c5f7..000000000000 --- a/lib/libesp32/Berry/src/be_baselib.c +++ /dev/null @@ -1,552 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_vm.h" -#include "be_exec.h" -#include "be_mem.h" -#include "be_gc.h" -#include "be_class.h" -#include "be_vector.h" -#include "be_string.h" -#include "be_map.h" -#include "be_strlib.h" -#include - -#define READLINE_STEP 100 - -int be_baselib_assert(bvm *vm) -{ - int argc = be_top(vm); - /* assertion fails when there is no argument - * or the first argument is nil or false. */ - if (!argc || !be_tobool(vm, 1)) { - const char *msg = "assert failed!"; - if (argc >= 2 && be_isstring(vm, 2)) { - msg = be_tostring(vm, 2); - } - be_raise(vm, "assert_failed", msg); - } - be_return_nil(vm); -} - -int be_baselib_print(bvm *vm) -{ - int i, argc = be_top(vm); - for (i = 1; i <= argc; ++i) { - const char *str = be_tostring(vm, i); - size_t len = be_strlen(vm, i); - be_writebuffer(str, len); - if (i < argc) { - be_writebuffer(" ", 1); - } - } - be_writenewline(); - be_return_nil(vm); -} - -static int m_readline(bvm *vm) -{ - size_t pos = 0, size = READLINE_STEP; - char *buffer = be_malloc(vm, size); - char *res = be_readstring(buffer, (int)size); - while (res) { - pos += strlen(buffer + pos) - 1; - if (!pos || buffer[pos] == '\n') { - buffer[pos] = '\0'; /* trim \n */ - break; - } - buffer = be_realloc(vm, buffer, size, size + READLINE_STEP); - res = be_readstring(buffer + pos + 1, READLINE_STEP); - size += READLINE_STEP; - } - be_pushstring(vm, buffer); - be_free(vm, buffer, size); - be_return(vm); -} - -int be_baselib_input(bvm *vm) -{ - if (be_top(vm) && be_isstring(vm, 1)) { /* echo prompt */ - be_writestring(be_tostring(vm, 1)); - } - return m_readline(vm); -} - -/* Look in the current class and all super classes for a method corresponding to a specific closure pointer */ -static bclass *find_class_closure(bclass *cl, bclosure *needle) -{ - while (cl) { - bmapnode *node; /* iterate on members of the class */ - bmap *members = be_class_members(cl); - if (members) { /* only iterate if there are members */ - bmapiter iter = be_map_iter(); - while ((node = be_map_next(members, &iter)) != NULL) { - if (var_primetype(&node->value) == BE_CLOSURE) { /* only native functions are considered */ - bclosure *clos_iter = var_toobj(&node->value); /* retrieve the method's closure */ - if (clos_iter == needle) { - /* we found the closure, we now know its class */ - return cl; - } - } - } - } - cl = be_class_super(cl); /* move to super class */ - } - return NULL; /* not found */ -} - -static bbool obj2int(bvm *vm, bvalue *var, bint *val) -{ - binstance *obj = var_toobj(var); - bstring *toint = str_literal(vm, "toint"); - /* get operator method */ - // TODO what if `tobool` is static - int type = be_instance_member(vm, obj, toint, vm->top); - if (type != BE_NONE && type != BE_NIL) { - vm->top[1] = *var; /* move self to argv[0] */ - be_dofunc(vm, vm->top, 1); /* call method 'tobool' */ - /* check the return value */ - if (var_isint(vm->top)) { - *val = var_toint(vm->top); - return btrue; - } - } - return bfalse; -} - -int be_baselib_super(bvm *vm) -{ - int argc = be_top(vm); - - /* if no argument, or arg 1 is nil, return nil */ - if (argc == 0 || be_isnil(vm, 1)) { - be_return_nil(vm); - } - - /* if arg 1 is a class, simply return super */ - if (be_isclass(vm, 1)) { - be_getsuper(vm, 1); - be_return(vm); - } - - /* arg 1 is an instance */ - if (be_isinstance(vm, 1)) { - binstance *o = var_toobj(be_indexof(vm, 1)); - bclass *target_class = NULL; /* the minimal class expected, or any super class */ - bclass *base_class = NULL; /* current class of the caller, if any */ - - /* if arg 2 is present, it must be a class */ - if (argc >= 2) { - if (be_isclass(vm, 2)) { - target_class = var_toobj(be_indexof(vm, 2)); - } else if (be_isnil(vm, 2)) { - // ignore, revert to standard super() behavior if second arg is explicit nil - } else { - be_raise(vm, "type_error", "leveled super() requires 'instance' and 'class' arguments"); - } - } - - /* now the more complex part, if arg 1 is an instance */ - /* if instance is the sole argument, try to find if it comes from a method of a class and set 'base_class' accordinly */ - /* later it will be equivalent to passing this class as second argument */ - if (argc == 1) { - /* we look in the callstack for the caller's closure */ - int size = be_stack_count(&vm->callstack); - if (size >= 2) { /* need at least 2 stackframes: current (for super() native) and caller (the one we are interested in) */ - bcallframe *caller = be_vector_at(&vm->callstack, size - 2); /* get the callframe of caller */ - bvalue *func = caller->func; /* function object of caller */ - if (var_primetype(func) == BE_CLOSURE) { /* only useful if the caller is a Berry closure (i.e. not native) */ - bclosure *clos_ctx = var_toobj(func); /* this is the closure we look for in the class chain */ - base_class = find_class_closure(o->_class, clos_ctx); /* iterate on current and super classes to find where the closure belongs */ - } - } - } - - if (base_class || target_class) { - if (base_class) { - target_class = base_class->super; - if (!target_class) be_return_nil(vm); /* fast exit if top class */ - } - /* leveled super, i.e. fix the parenthood class level */ - if (o) { - o = be_instance_super(o); /* always skip the current class and move to super */ - } - while (o) { - bclass *c = be_instance_class(o); - if (c == target_class) break; /* found */ - o = be_instance_super(o); - } - bvalue *top = be_incrtop(vm); - if (o) { - var_setinstance(top, o); /* return the instance with the specified parent class */ - } else { - var_setnil(top); /* not found, return nil */ - } - be_return(vm); - } else { - be_getsuper(vm, 1); - be_return(vm); - } - } - - /* fall through, return nil if we don't know what to do */ - be_return_nil(vm); -} - -int be_baselib_type(bvm *vm) -{ - if (be_top(vm)) { - be_pushstring(vm, be_typename(vm, 1)); - be_return(vm); - } - be_return_nil(vm); -} - -int be_baselib_classname(bvm *vm) -{ - if (be_top(vm)) { - const char *t = be_classname(vm, 1); - if (t) { - be_pushstring(vm, t); - be_return(vm); - } - } - be_return_nil(vm); -} - -int be_baselib_classof(bvm *vm) -{ - if (be_top(vm) && be_classof(vm, 1)) { - be_return(vm); - } - be_return_nil(vm); -} - -int be_baselib_number(bvm *vm) -{ - if (be_top(vm)) { - if (be_isstring(vm, 1)) { - be_str2num(vm, be_tostring(vm, 1)); - be_return(vm); - } else if (be_isnumber(vm, 1)) { - be_pushvalue(vm, 1); - be_return(vm); - } - } - be_return_nil(vm); -} - -int be_baselib_int(bvm *vm) -{ - if (be_top(vm)) { - if (be_isstring(vm, 1)) { - const char *s = be_tostring(vm, 1); - be_pushint(vm, be_str2int(s, NULL)); - } else if (be_isreal(vm, 1)) { - be_pushint(vm, (bint)be_toreal(vm, 1)); - } else if (be_isint(vm, 1)) { - be_pushvalue(vm, 1); - } else if (be_isbool(vm, 1)) { - be_pushint(vm, be_tobool(vm, 1) ? 1 : 0); - } else if (be_iscomptr(vm, 1)) { - intptr_t p = (intptr_t) be_tocomptr(vm, 1); - be_pushint(vm, (int) p); - } else if (be_isinstance(vm, 1)) { - /* try to call `toint` method */ - bvalue *v = be_indexof(vm, 1); - bint val; - if (obj2int(vm, v, &val)) { - be_pushint(vm, val); - } else { - be_return_nil(vm); - } - } else { - be_return_nil(vm); - } - be_return(vm); - } - be_return_nil(vm); -} - -int be_baselib_real(bvm *vm) -{ - if (be_top(vm)) { - if (be_isstring(vm, 1)) { - const char *s = be_tostring(vm, 1); - be_pushreal(vm, be_str2real(s, NULL)); - } else if (be_isint(vm, 1)) { - be_pushreal(vm, (breal)be_toint(vm, 1)); - } else if (be_isreal(vm, 1)) { - be_pushvalue(vm, 1); - } else { - be_return_nil(vm); - } - be_return(vm); - } - be_return_nil(vm); -} - -static int check_method(bvm *vm, const char *attr) -{ - return be_top(vm) && - be_isinstance(vm, 1) && be_getmethod(vm, 1, attr); -} - -int be_baselib_iterator(bvm *vm) -{ - if (be_top(vm) && be_isfunction(vm, 1)) { - be_return(vm); /* return the argument[0]::function */ - } - if (check_method(vm, "iter")) { - be_pushvalue(vm, 1); - be_call(vm, 1); - be_pop(vm, 1); - be_return(vm); - } - be_return_nil(vm); -} - -/* call a function with variable number of arguments */ -/* first argument is a callable object (function, closure, native function, native closure) */ -/* then all subsequent arguments are pushed except the last one */ -/* If the last argument is a 'list', then all elements are pushed as arguments */ -/* otherwise the last argument is pushed as well */ -static int l_call(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1 && be_isfunction(vm, 1)) { - size_t arg_count = top - 1; /* we have at least 'top - 1' arguments */ - /* test if last argument is a list */ - - if (top > 1 && be_isinstance(vm, top) && be_getmember(vm, top, ".p") && be_islist(vm, top + 1)) { - int32_t list_size = be_data_size(vm, top + 1); - - if (list_size > 0) { - be_stack_require(vm, list_size + 3); /* make sure we don't overflow the stack */ - for (int i = 0; i < list_size; i++) { - be_pushnil(vm); - } - be_moveto(vm, top + 1, top + 1 + list_size); - be_moveto(vm, top, top + list_size); - - be_pushiter(vm, -1); - while (be_iter_hasnext(vm, -2)) { - be_iter_next(vm, -2); - be_moveto(vm, -1, top); - top++; - be_pop(vm, 1); - } - be_pop(vm, 1); /* remove iterator */ - } - be_pop(vm, 2); - arg_count = arg_count - 1 + list_size; - } - /* actual call */ - be_call(vm, arg_count); - /* remove args */ - be_pop(vm, arg_count); - /* return value */ - - be_return(vm); - } - be_raise(vm, "value_error", "first argument must be a function"); - be_return_nil(vm); -} - -int be_baselib_str(bvm *vm) -{ - if (be_top(vm)) { - be_tostring(vm, 1); - } else { - be_pushstring(vm, ""); - } - be_return(vm); -} - -static int l_bool(bvm *vm) -{ - if (be_top(vm)) { - be_pushbool(vm, be_tobool(vm, 1)); - } else { - be_pushbool(vm, bfalse); - } - be_return(vm); -} - - -int be_baselib_size(bvm *vm) -{ - if (be_top(vm) && be_isstring(vm, 1)) { - be_pushint(vm, be_strlen(vm, 1)); - be_return(vm); - } - if (check_method(vm, "size")) { - be_pushvalue(vm, 1); - be_call(vm, 1); - be_pop(vm, 1); - be_return(vm); - } - be_return_nil(vm); -} - -int be_baselib_module(bvm *vm) -{ - int argc = be_top(vm); - be_newmodule(vm); - if (argc > 0 && be_isstring(vm, 1)) { - be_setname(vm, -1, be_tostring(vm, 1)); - } - be_return(vm); -} - -#if BE_USE_SCRIPT_COMPILER -static int raise_compile_error(bvm *vm) -{ - be_pop(vm, 2); /* pop the exception value and message */ - be_throw(vm, BE_EXCEPTION); - return 0; -} - -static int m_compile_str(bvm *vm) -{ - int len = be_strlen(vm, 1); - const char *src = be_tostring(vm, 1); - int res = be_loadbuffer(vm, "string", src, len); - if (res == BE_OK) { - be_return(vm); - } - return raise_compile_error(vm); -} - -static int m_compile_file(bvm *vm) -{ - const char *fname = be_tostring(vm, 1); - int res = be_loadfile(vm, fname); - if (res == BE_OK) { - be_return(vm); - } else if (res == BE_IO_ERROR) { - be_pushstring(vm, "io_error"); - be_pushvalue(vm, -2); - } - return raise_compile_error(vm); -} -#endif - -int be_baselib_compile(bvm *vm) -{ -#if BE_USE_SCRIPT_COMPILER - if (be_top(vm) && be_isstring(vm, 1)) { - if (be_top(vm) >= 2 && be_isstring(vm, 2)) { - const char *s = be_tostring(vm, 2); - if (!strcmp(s, "string")) { - return m_compile_str(vm); - } - if (!strcmp(s, "file")) { - return m_compile_file(vm); - } - } else { - return m_compile_str(vm); - } - } -#endif - be_return_nil(vm); -} - -static int _issubv(bvm *vm, bbool (*filter)(bvm*, int)) -{ - bbool status = bfalse; - if (be_top(vm) >= 2 && filter(vm, 1)) { - be_pushvalue(vm, 2); - status = be_isderived(vm, 1); - } - be_pushbool(vm, status); - be_return(vm); -} - -int be_baselib_issubclass(bvm *vm) -{ - return _issubv(vm, be_isclass); -} - -int be_baselib_isinstance(bvm *vm) -{ - return _issubv(vm, be_isinstance); -} - -#if !BE_USE_PRECOMPILED_OBJECT -void be_load_baselib(bvm *vm) -{ - be_regfunc(vm, "assert", be_baselib_assert); - be_regfunc(vm, "print", be_baselib_print); - be_regfunc(vm, "input", be_baselib_input); - be_regfunc(vm, "super", be_baselib_super); - be_regfunc(vm, "type", be_baselib_type); - be_regfunc(vm, "classname", be_baselib_classname); - be_regfunc(vm, "classof", be_baselib_classof); - be_regfunc(vm, "number", be_baselib_number); - be_regfunc(vm, "str", be_baselib_str); - be_regfunc(vm, "int", be_baselib_int); - be_regfunc(vm, "real", be_baselib_real); - be_regfunc(vm, "module", be_baselib_module); - be_regfunc(vm, "size", be_baselib_size); - be_regfunc(vm, "compile", be_baselib_compile); - be_regfunc(vm, "issubclass", be_baselib_issubclass); - be_regfunc(vm, "isinstance", be_baselib_isinstance); - be_regfunc(vm, "__iterator__", be_baselib_iterator); -} - -/* call must be added later to respect order of builtins */ -void be_load_baselib_next(bvm *vm) -{ - be_regfunc(vm, "call", l_call); - be_regfunc(vm, "bool", l_bool); - be_regfunc(vm, "format", be_str_format); -} -#else -extern const bclass be_class_list; -extern const bclass be_class_map; -extern const bclass be_class_range; -extern const bclass be_class_bytes; -extern int be_nfunc_open(bvm *vm); -/* @const_object_info_begin -vartab m_builtin (scope: local) { - assert, func(be_baselib_assert) - print, func(be_baselib_print) - input, func(be_baselib_input) - super, func(be_baselib_super) - type, func(be_baselib_type) - classname, func(be_baselib_classname) - classof, func(be_baselib_classof) - number, func(be_baselib_number) - str, func(be_baselib_str) - int, func(be_baselib_int) - real, func(be_baselib_real) - module, func(be_baselib_module) - size, func(be_baselib_size) - compile, func(be_baselib_compile) - issubclass, func(be_baselib_issubclass) - isinstance, func(be_baselib_isinstance) - __iterator__, func(be_baselib_iterator) - open, func(be_nfunc_open) - list, class(be_class_list) - map, class(be_class_map) - range, class(be_class_range) - bytes, class(be_class_bytes) - call, func(l_call) - bool, func(l_bool) - format, func(be_str_format) -} -@const_object_info_end */ -#include "../generate/be_fixed_m_builtin.h" -#include "be_var.h" - -void be_load_baselib(bvm *vm) -{ - be_const_builtin_set(vm, &m_builtin_map, &m_builtin_vector); -} -#endif diff --git a/lib/libesp32/Berry/src/be_bytecode.c b/lib/libesp32/Berry/src/be_bytecode.c deleted file mode 100644 index 79ed503bd95d..000000000000 --- a/lib/libesp32/Berry/src/be_bytecode.c +++ /dev/null @@ -1,634 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_bytecode.h" -#include "be_decoder.h" -#include "be_vector.h" -#include "be_string.h" -#include "be_class.h" -#include "be_func.h" -#include "be_exec.h" -#include "be_list.h" -#include "be_map.h" -#include "be_mem.h" -#include "be_sys.h" -#include "be_var.h" -#include "be_vm.h" -#include - -#define MAGIC_NUMBER1 0xBE -#define MAGIC_NUMBER2 0xCD -#define MAGIC_NUMBER3 0xFE -#define BYTECODE_VERSION 4 - -#define USE_64BIT_INT (BE_INTGER_TYPE == 2 \ - || BE_INTGER_TYPE == 1 && LONG_MAX == 9223372036854775807L) - -#if !BE_USE_SCRIPT_COMPILER && BE_USE_BYTECODE_SAVER -#error bytecode generation dependent compiler (require BE_USE_SCRIPT_COMPILER != 0) -#endif - -#if BE_USE_BYTECODE_SAVER || BE_USE_BYTECODE_LOADER -static void bytecode_error(bvm *vm, const char *msg) -{ - be_raise(vm, "io_error", msg); -} - -static uint8_t vm_sizeinfo(void) -{ - uint8_t res = sizeof(bint) == 8; - res |= (sizeof(breal) == 8) << 1; - return res; -} -#endif - -#if BE_USE_BYTECODE_SAVER -static void save_proto(bvm *vm, void *fp, bproto *proto); - -static void save_byte(void *fp, uint8_t value) -{ - be_fwrite(fp, &value, 1); -} - -static void save_word(void *fp, uint16_t value) -{ - uint8_t buffer[2]; - buffer[0] = value & 0xff; - buffer[1] = value >> 8; - be_fwrite(fp, buffer, sizeof(buffer)); -} - -static void save_long(void *fp, uint32_t value) -{ - uint8_t buffer[4]; - buffer[0] = value & 0xff; - buffer[1] = (value >> 8) & 0xff; - buffer[2] = (value >> 16) & 0xff; - buffer[3] = (value >> 24) & 0xff; - be_fwrite(fp, buffer, sizeof(buffer)); -} - -static void save_header(void *fp) -{ - uint8_t buffer[8] = { 0 }; - buffer[0] = MAGIC_NUMBER1; - buffer[1] = MAGIC_NUMBER2; - buffer[2] = MAGIC_NUMBER3; - buffer[3] = BYTECODE_VERSION; - buffer[4] = vm_sizeinfo(); - be_fwrite(fp, buffer, sizeof(buffer)); -} - -static void save_int(void *fp, bint i) -{ -#if USE_64BIT_INT - save_long(fp, i & 0xffffffff); - save_long(fp, (i >> 32) & 0xffffffff); -#else - save_long(fp, (uint32_t)i); -#endif -} - -static void save_real(void *fp, breal r) -{ -#if BE_USE_SINGLE_FLOAT - union { breal r; uint32_t i; } u; - u.r = r; - save_long(fp, u.i); -#else - union { breal r; uint64_t i; } u; - u.r = r; - save_long(fp, u.i & 0xffffffff); - save_long(fp, (u.i >> 32) & 0xffffffff); -#endif -} - -static void save_string(void *fp, bstring *s) -{ - if (s) { - uint16_t length = (uint16_t)str_len(s); - const char *data = str(s); - save_word(fp, length); - be_fwrite(fp, data, length); - } else { - save_word(fp, 0); - } -} - -static bstring** save_members(bvm *vm, void *fp, bclass *c, int nvar) -{ - bmapnode *node; - bstring **vars = NULL; - bmap *members = c->members; - bmapiter iter = be_map_iter(); - if (nvar) { - /* allocate the member-variable name cache */ - vars = be_malloc(vm, sizeof(bstring *) * nvar); - } - while ((node = be_map_next(members, &iter)) != NULL) { - be_assert(var_isstr(&node->key)); - if (var_isindex(&node->value)) { /* cache member name */ - if (vars == NULL) { - return NULL; /* should never be executed */ - } - vars[var_toidx(&node->value)] = var_tostr(&node->key); - } else { /* save method's name and function */ - bproto *proto; - bvalue *value = &node->value; - be_assert(var_isclosure(value) || var_isproto(value) || var_isnil(value)); - save_string(fp, var_tostr(&node->key)); /* save method name */ - if (var_isproto(value)) { /* the method is a prototype */ - proto = var_toobj(value); - save_proto(vm, fp, proto); /* only save prototype */ - } else if (var_isclosure(value)) { /* the method is a closure */ - proto = cast(bclosure *, var_toobj(value))->proto; - save_proto(vm, fp, proto); /* only save prototype */ - } else if (var_isnil(value)) { - /* this is a static member (nil default) */ - save_word(fp, 0); /* store a zero byte that will be seen as a zero length method name which is invalid */ - } else { - be_raise(vm, "internal_error", "unsupported member in class"); - return NULL; /* should never be executed */ - } - } - } - return vars; -} - -static void save_class(bvm *vm, void *fp, bclass *c) -{ - bstring **vars; - int i, count = c->members ? be_map_count(c->members) : 0; - int nvar = c->nvar - be_class_closure_count(c); - save_string(fp, c->name); - save_long(fp, nvar); /* member variables count */ - save_long(fp, count - nvar); /* method count */ - if (count > 0) { - vars = save_members(vm, fp, c, nvar); - if (vars != NULL) { - for (i = 0; i < nvar; ++i) { - save_string(fp, vars[i]); - } - be_free(vm, vars, sizeof(bstring *) * nvar); - } - } -} - -static void save_value(bvm *vm, void *fp, bvalue *v) -{ - save_byte(fp, (uint8_t)var_primetype(v)); /* type */ - switch (var_primetype(v)) { - case BE_INT: save_int(fp, var_toint(v)); break; - case BE_REAL: save_real(fp, var_toreal(v)); break; - case BE_STRING: save_string(fp, var_tostr(v)); break; - case BE_CLASS: save_class(vm, fp, var_toobj(v)); break; - default: break; - } -} - -static void save_bytecode(bvm *vm, void *fp, bproto *proto) -{ - int forbid_gbl = comp_is_named_gbl(vm); - binstruction *code = proto->code, *end; - save_long(fp, (uint32_t)proto->codesize); - for (end = code + proto->codesize; code < end; ++code) { - save_long(fp, (uint32_t)*code); - if (forbid_gbl) { /* we are saving only named globals, so make sure we don't save OP_GETGBL or OP_SETGBL */ - if ((uint32_t)*code == OP_GETGBL || (uint32_t)*code == OP_SETGBL) { - be_raise(vm, "internal_error", "GETGBL/SETGBL found when saving with named globals"); - } - } - } -} - -static void save_constants(bvm *vm, void *fp, bproto *proto) -{ - bvalue *v = proto->ktab, *end; - save_long(fp, proto->nconst); /* constants count */ - for (end = v + proto->nconst; v < end; ++v) { - if ((v == proto->ktab) && (proto->varg & BE_VA_STATICMETHOD) && (v->type == BE_CLASS)) { - /* implicit `_class` parameter, output nil */ - bvalue v_nil; - v_nil.v.i = 0; - v_nil.type = BE_NIL; - save_value(vm, fp, &v_nil); - } else { - save_value(vm, fp, v); - } - } -} - -static void save_proto_table(bvm *vm, void *fp, bproto *proto) -{ - bproto **p = proto->ptab, **end; - save_long(fp, proto->nproto); /* proto count */ - if (p) { - for (end = p + proto->nproto; p < end; ++p) { - save_proto(vm, fp, *p); - } - } -} - -static void save_upvals(void *fp, bproto *proto) -{ - bupvaldesc *uv = proto->upvals, *end; - save_byte(fp, proto->nupvals); /* upvals count */ - if (uv) { - for (end = uv + proto->nupvals; uv < end; ++uv) { - save_byte(fp, uv->instack); - save_byte(fp, uv->idx); - } - } -} - -static void save_proto(bvm *vm, void *fp, bproto *proto) -{ - if (proto) { - save_string(fp, proto->name); /* name */ -#if BE_DEBUG_SOURCE_FILE - save_string(fp, proto->source); /* source */ -#else - save_string(fp, NULL); /* source */ -#endif - save_byte(fp, proto->argc); /* argc */ - save_byte(fp, proto->nstack); /* nstack */ - save_byte(fp, proto->varg); /* varg */ - save_byte(fp, 0x00); /* reserved */ - save_bytecode(vm, fp, proto); /* bytecode */ - save_constants(vm, fp, proto); /* constant */ - save_proto_table(vm, fp, proto); /* proto table */ - save_upvals(fp, proto); /* upvals description table */ - } -} - -static void save_globals(bvm *vm, void *fp) -{ - bmapnode *node; - bmapiter iter = be_map_iter(); - bmap *map = vm->gbldesc.global.vtab; - int i, count = be_global_count(vm); - bstring **list = be_malloc(vm, sizeof(bstring*) * count); - while ((node = be_map_next(map, &iter)) != NULL) { - if (var_isstr(&node->key)) { - int idx = var_toidx(&node->value); - be_assert(idx < count); - list[idx] = var_tostr(&node->key); - } - } - for (i = 0; i < count; ++i) { - save_string(fp, list[i]); - } - be_free(vm, list, sizeof(bstring*) * count); -} - -static void save_global_info(bvm *vm, void *fp) -{ - save_long(fp, be_builtin_count(vm)); - if (comp_is_named_gbl(vm)) { - /* named globals only so no need to save current globals */ - save_long(fp, 0); - } else { - save_long(fp, be_global_count(vm)); - save_globals(vm, fp); - } -} - -void be_bytecode_save_to_fs(bvm *vm, void *fp, bproto *proto) -{ - save_header(fp); - save_global_info(vm, fp); - save_proto(vm, fp, proto); -} - -void be_bytecode_save(bvm *vm, const char *filename, bproto *proto) -{ - void *fp = be_fopen(filename, "wb"); - if (fp == NULL) { - bytecode_error(vm, be_pushfstring(vm, - "can not open file '%s'.", filename)); - } else { - be_bytecode_save_to_fs(vm, fp, proto); - be_fclose(fp); - } -} -#endif /* BE_USE_BYTECODE_SAVER */ - -#if BE_USE_BYTECODE_LOADER -static bbool load_proto(bvm *vm, void *fp, bproto **proto, int info, int version); - -static uint8_t load_byte(void *fp) -{ - uint8_t buffer[1]; - if (be_fread(fp, buffer, sizeof(buffer)) == sizeof(buffer)) { - return buffer[0]; - } - return 0; -} - -static uint16_t load_word(void *fp) -{ - uint8_t buffer[2]; - if (be_fread(fp, buffer, sizeof(buffer)) == sizeof(buffer)) { - return ((uint16_t)buffer[1] << 8) | buffer[0]; - } - return 0; -} - -static uint32_t load_long(void *fp) -{ - uint8_t buffer[4]; - if (be_fread(fp, buffer, sizeof(buffer)) == sizeof(buffer)) { - return ((uint32_t)buffer[3] << 24) - | ((uint32_t)buffer[2] << 16) - | ((uint32_t)buffer[1] << 8) - | buffer[0]; - } - return 0; -} - -static int load_head(void *fp) -{ - int res; - uint8_t buffer[8] = { 0 }; - be_fread(fp, buffer, sizeof(buffer)); - res = buffer[0] == MAGIC_NUMBER1 && - buffer[1] == MAGIC_NUMBER2 && - buffer[2] == MAGIC_NUMBER3 && - buffer[4] == vm_sizeinfo(); - if (res) { - return buffer[3]; - } else { - return 0; - } -} - -bbool be_bytecode_check(const char *path) -{ - void *fp = be_fopen(path, "r"); - if (fp) { - uint8_t buffer[3], rb; - rb = (uint8_t)be_fread(fp, buffer, 3); - be_fclose(fp); - /* check magic number */ - return rb == 3 && - buffer[0] == MAGIC_NUMBER1 && - buffer[1] == MAGIC_NUMBER2 && - buffer[2] == MAGIC_NUMBER3; - } - return bfalse; -} - -static bint load_int(void *fp) -{ -#if USE_64BIT_INT - bint i; - i = load_long(fp); - i |= (bint)load_long(fp) << 32; - return i; -#else - return load_long(fp); -#endif -} - -static breal load_real(void *fp) -{ -#if BE_USE_SINGLE_FLOAT - union { breal r; uint32_t i; } u; - u.i = load_long(fp); - return u.r; -#else - union { - breal r; - uint64_t i; - } u; - u.i = load_long(fp); - u.i |= (uint64_t)load_long(fp) << 32; - return u.r; -#endif -} - -static bstring* load_string(bvm *vm, void *fp) -{ - uint16_t len = load_word(fp); - if (len > 0) { - bstring *str; - char *buf = be_malloc(vm, len); - be_fread(fp, buf, len); - str = be_newstrn(vm, buf, len); - be_free(vm, buf, len); - return str; - } - return str_literal(vm, ""); -} - -static bstring* cache_string(bvm *vm, void *fp) -{ - bstring *str = load_string(vm, fp); - var_setstr(vm->top, str); - be_incrtop(vm); - return str; -} - -static void load_class(bvm *vm, void *fp, bvalue *v, int version) -{ - int nvar, count; - bclass *c = be_newclass(vm, NULL, NULL); - var_setclass(v, c); - c->name = load_string(vm, fp); - nvar = load_long(fp); - count = load_long(fp); - while (count--) { /* load method table */ - bvalue *value; - bstring *name = cache_string(vm, fp); - value = vm->top; - var_setproto(value, NULL); - be_incrtop(vm); - if (load_proto(vm, fp, (bproto**)&var_toobj(value), -3, version)) { - /* actual method */ - bproto *proto = (bproto*)var_toobj(value); - bbool is_method = proto->varg & BE_VA_METHOD; - if (!is_method) { - if ((proto->nconst > 0) && (proto->ktab->type == BE_NIL)) { - /* The first argument is nil so we replace with the class as implicit '_class' */ - proto->ktab->type = BE_CLASS; - proto->ktab->v.p = c; - } - } - be_class_method_bind(vm, c, name, var_toobj(value), !is_method); - } else { - /* no proto, static member set to nil */ - be_class_member_bind(vm, c, name, bfalse); - } - be_stackpop(vm, 2); /* pop the cached string and proto */ - } - for (count = 0; count < nvar; ++count) { /* load member-variable table */ - bstring *name = cache_string(vm, fp); - be_class_member_bind(vm, c, name, btrue); - be_stackpop(vm, 1); /* pop the cached string */ - } -} - -static void load_value(bvm *vm, void *fp, bvalue *v, int version) -{ - switch (load_byte(fp)) { - case BE_INT: var_setint(v, load_int(fp)); break; - case BE_REAL: var_setreal(v, load_real(fp)); break; - case BE_STRING: var_setstr(v, load_string(vm, fp)); break; - case BE_CLASS: load_class(vm, fp, v, version); break; - default: break; - } -} - -static void load_bytecode(bvm *vm, void *fp, bproto *proto, int info) -{ - int size = (int)load_long(fp); - if (size) { - binstruction *code, *end; - int bcnt = be_builtin_count(vm); - blist *list = var_toobj(be_indexof(vm, info)); - be_assert(be_islist(vm, info)); - proto->code = be_malloc(vm, sizeof(binstruction) * size); - proto->codesize = size; - code = proto->code; - for (end = code + size; code < end; ++code) { - binstruction ins = (binstruction)load_long(fp); - binstruction op = IGET_OP(ins); - /* fix global variable index */ - if (op == OP_GETGBL || op == OP_SETGBL) { - int idx = IGET_Bx(ins); - if (idx >= bcnt) { /* does not fix builtin index */ - bvalue *name = be_list_at(list, idx - bcnt); - idx = be_global_find(vm, var_tostr(name)); - ins = (ins & ~IBx_MASK) | ISET_Bx(idx); - } - } - *code = ins; - } - } -} - -static void load_constant(bvm *vm, void *fp, bproto *proto, int version) -{ - int size = (int)load_long(fp); /* nconst */ - if (size) { - bvalue *end, *v = be_malloc(vm, sizeof(bvalue) * size); - memset(v, 0, sizeof(bvalue) * size); - proto->ktab = v; - proto->nconst = size; - for (end = v + size; v < end; ++v) { - load_value(vm, fp, v, version); - } - } -} - -static void load_proto_table(bvm *vm, void *fp, bproto *proto, int info, int version) -{ - int size = (int)load_long(fp); /* proto count */ - if (size) { - bproto **p = be_malloc(vm, sizeof(bproto *) * size); - memset(p, 0, sizeof(bproto *) * size); - proto->ptab = p; - proto->nproto = size; - while (size--) { - load_proto(vm, fp, p++, info, version); - } - } -} - -static void load_upvals(bvm *vm, void *fp, bproto *proto) -{ - int size = (int)load_byte(fp); - if (size) { - bupvaldesc *uv, *end; - proto->upvals = be_malloc(vm, sizeof(bupvaldesc) * size); - proto->nupvals = (bbyte)size; - uv = proto->upvals; - for (end = uv + size; uv < end; ++uv) { - uv->instack = load_byte(fp); - uv->idx = load_byte(fp); - } - } -} - -static bbool load_proto(bvm *vm, void *fp, bproto **proto, int info, int version) -{ - /* first load the name */ - /* if empty, it's a static member so don't allocate an actual proto */ - bstring *name = load_string(vm, fp); - if (str_len(name)) { - *proto = be_newproto(vm); - (*proto)->name = name; -#if BE_DEBUG_SOURCE_FILE - (*proto)->source = load_string(vm, fp); -#else - load_string(vm, fp); /* discard name */ -#endif - (*proto)->argc = load_byte(fp); - (*proto)->nstack = load_byte(fp); - if (version > 1) { - (*proto)->varg = load_byte(fp); - load_byte(fp); /* discard reserved byte */ - } - load_bytecode(vm, fp, *proto, info); - load_constant(vm, fp, *proto, version); - load_proto_table(vm, fp, *proto, info, version); - load_upvals(vm, fp, *proto); - return btrue; - } - return bfalse; /* no proto read */ -} - -void load_global_info(bvm *vm, void *fp) -{ - int i; - int bcnt = (int)load_long(fp); /* builtin count */ - int gcnt = (int)load_long(fp); /* global count */ - if (bcnt > be_builtin_count(vm)) { - bytecode_error(vm, be_pushfstring(vm, - "inconsistent number of builtin objects.")); - } - be_newlist(vm); - for (i = 0; i < gcnt; ++i) { - bstring *name = cache_string(vm, fp); - be_global_new(vm, name); - be_data_push(vm, -2); /* push the variable name to list */ - be_stackpop(vm, 1); /* pop the cached string */ - } - be_global_release_space(vm); -} - -bclosure* be_bytecode_load_from_fs(bvm *vm, void *fp) -{ - int version = load_head(fp); - if (version == BYTECODE_VERSION) { - bclosure *cl = be_newclosure(vm, 0); - var_setclosure(vm->top, cl); - be_stackpush(vm); - load_global_info(vm, fp); - load_proto(vm, fp, &cl->proto, -1, version); - be_stackpop(vm, 2); /* pop the closure and list */ - be_fclose(fp); - return cl; - } - bytecode_error(vm, be_pushfstring(vm, - "invalid bytecode version.")); - return NULL; -} - -bclosure* be_bytecode_load(bvm *vm, const char *filename) -{ - void *fp = be_fopen(filename, "rb"); - if (fp == NULL) { - bytecode_error(vm, be_pushfstring(vm, - "can not open file '%s'.", filename)); - } else { - return be_bytecode_load_from_fs(vm, fp); - } - return NULL; -} - -#endif /* BE_USE_BYTECODE_LOADER */ diff --git a/lib/libesp32/Berry/src/be_bytecode.h b/lib/libesp32/Berry/src/be_bytecode.h deleted file mode 100644 index 4e1d54a3b58c..000000000000 --- a/lib/libesp32/Berry/src/be_bytecode.h +++ /dev/null @@ -1,19 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef __BE_BYTECODE_H -#define __BE_BYTECODE_H - -#include "be_object.h" - -void be_bytecode_save(bvm *vm, const char *filename, bproto *proto); -void be_bytecode_save_to_fs(bvm *vm, void *fp, bproto *proto); -bclosure* be_bytecode_load(bvm *vm, const char *filename); -bclosure* be_bytecode_load_from_fs(bvm *vm, void *fp); -bbool be_bytecode_check(const char *path); - -#endif diff --git a/lib/libesp32/Berry/src/be_byteslib.c b/lib/libesp32/Berry/src/be_byteslib.c deleted file mode 100644 index 460de413e6eb..000000000000 --- a/lib/libesp32/Berry/src/be_byteslib.c +++ /dev/null @@ -1,1907 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang - Stephan Hadinger -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_string.h" -#include "be_strlib.h" -#include "be_list.h" -#include "be_func.h" -#include "be_exec.h" -#include "be_vm.h" -#include "be_mem.h" -#include "be_constobj.h" -#include -#include -#include "be_byteslib.h" - -/******************************************************************** -** Base64 lib from https://github.com/Densaugeo/base64_arduino -** -********************************************************************/ - -/* binary_to_base64: - * Description: - * Converts a single byte from a binary value to the corresponding base64 character - * Parameters: - * v - Byte to convert - * Returns: - * ascii code of base64 character. If byte is >= 64, then there is not corresponding base64 character - * and 255 is returned - */ -static unsigned char binary_to_base64(unsigned char v); - -/* base64_to_binary: - * Description: - * Converts a single byte from a base64 character to the corresponding binary value - * Parameters: - * c - Base64 character (as ascii code) - * Returns: - * 6-bit binary value - */ -static unsigned char base64_to_binary(unsigned char c); - -/* encode_base64_length: - * Description: - * Calculates length of base64 string needed for a given number of binary bytes - * Parameters: - * input_length - Amount of binary data in bytes - * Returns: - * Number of base64 characters needed to encode input_length bytes of binary data - */ -static unsigned int encode_base64_length(unsigned int input_length); - -/* decode_base64_length: - * Description: - * Calculates number of bytes of binary data in a base64 string - * Parameters: - * input - Base64-encoded null-terminated string - * Returns: - * Number of bytes of binary data in input - */ -static unsigned int decode_base64_length(unsigned char input[]); - -/* encode_base64: - * Description: - * Converts an array of bytes to a base64 null-terminated string - * Parameters: - * input - Pointer to input data - * input_length - Number of bytes to read from input pointer - * output - Pointer to output string. Null terminator will be added automatically - * Returns: - * Length of encoded string in bytes (not including null terminator) - */ -static unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]); - -/* decode_base64: - * Description: - * Converts a base64 null-terminated string to an array of bytes - * Parameters: - * input - Pointer to input string - * output - Pointer to output array - * Returns: - * Number of bytes in the decoded binary - */ -static unsigned int decode_base64(unsigned char input[], unsigned char output[]); - -static unsigned char binary_to_base64(unsigned char v) { - // Capital letters - 'A' is ascii 65 and base64 0 - if(v < 26) return v + 'A'; - - // Lowercase letters - 'a' is ascii 97 and base64 26 - if(v < 52) return v + 71; - - // Digits - '0' is ascii 48 and base64 52 - if(v < 62) return v - 4; - - // '+' is ascii 43 and base64 62 - if(v == 62) return '+'; - - // '/' is ascii 47 and base64 63 - if(v == 63) return '/'; - - return 64; -} - -static unsigned char base64_to_binary(unsigned char c) { - // Capital letters - 'A' is ascii 65 and base64 0 - if('A' <= c && c <= 'Z') return c - 'A'; - - // Lowercase letters - 'a' is ascii 97 and base64 26 - if('a' <= c && c <= 'z') return c - 71; - - // Digits - '0' is ascii 48 and base64 52 - if('0' <= c && c <= '9') return c + 4; - - // '+' is ascii 43 and base64 62 - if(c == '+') return 62; - - // '/' is ascii 47 and base64 63 - if(c == '/') return 63; - - return 255; -} - -static unsigned int encode_base64_length(unsigned int input_length) { - return (input_length + 2)/3*4; -} - -static unsigned int decode_base64_length(unsigned char input[]) { - unsigned char *start = input; - - while(base64_to_binary(input[0]) < 64) { - ++input; - } - - unsigned int input_length = input - start; - - unsigned int output_length = input_length/4*3; - - switch(input_length % 4) { - default: return output_length; - case 2: return output_length + 1; - case 3: return output_length + 2; - } -} - -static unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]) { - unsigned int full_sets = input_length/3; - - // While there are still full sets of 24 bits... - for(unsigned int i = 0; i < full_sets; ++i) { - output[0] = binary_to_base64( input[0] >> 2); - output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4); - output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6); - output[3] = binary_to_base64( input[2] & 0x3F); - - input += 3; - output += 4; - } - - switch(input_length % 3) { - case 0: - output[0] = '\0'; - break; - case 1: - output[0] = binary_to_base64( input[0] >> 2); - output[1] = binary_to_base64((input[0] & 0x03) << 4); - output[2] = '='; - output[3] = '='; - output[4] = '\0'; - break; - case 2: - output[0] = binary_to_base64( input[0] >> 2); - output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4); - output[2] = binary_to_base64((input[1] & 0x0F) << 2); - output[3] = '='; - output[4] = '\0'; - break; - } - - return encode_base64_length(input_length); -} - -static unsigned int decode_base64(unsigned char input[], unsigned char output[]) { - unsigned int output_length = decode_base64_length(input); - - // While there are still full sets of 24 bits... - for(unsigned int i = 2; i < output_length; i += 3) { - output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4; - output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2; - output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]); - - input += 4; - output += 3; - } - - switch(output_length % 3) { - case 1: - output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4; - break; - case 2: - output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4; - output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2; - break; - } - - return output_length; -} - -/******************************************************************** -** Buffer low-level implementation -** -** Extracted from Tasmota SBuffer lib -********************************************************************/ -// static inline uint8_t* buf_get_buf(buf_impl* attr) -// { -// return &attr->bufptr[0]; -// } - -// shrink or increase. If increase, fill with zeores. Cannot go beyond `size` -static void buf_set_len(buf_impl* attr, const size_t len) -{ - int32_t old_len = attr->len; - attr->len = ((int32_t)len <= attr->size) ? (int32_t)len : attr->size; - if (old_len < attr->len) { - memset((void*) &attr->bufptr[old_len], 0, attr->len - old_len); - } -} - -static size_t buf_add1(buf_impl* attr, const uint8_t data) // append 8 bits value -{ - if (attr->len < attr->size) { // do we have room for 1 byte - attr->bufptr[attr->len++] = data; - } - return attr->len; -} - -static size_t buf_add2_le(buf_impl* attr, const uint16_t data) // append 16 bits value -{ - if (attr->len < attr->size - 1) { // do we have room for 2 bytes - attr->bufptr[attr->len++] = data; - attr->bufptr[attr->len++] = data >> 8; - } - return attr->len; -} - -static size_t buf_add2_be(buf_impl* attr, const uint16_t data) // append 16 bits value -{ - if (attr->len < attr->size - 1) { // do we have room for 2 bytes - attr->bufptr[attr->len++] = data >> 8; - attr->bufptr[attr->len++] = data; - } - return attr->len; -} - -static size_t buf_add4_le(buf_impl* attr, const uint32_t data) // append 32 bits value -{ - if (attr->len < attr->size - 3) { // do we have room for 4 bytes - attr->bufptr[attr->len++] = data; - attr->bufptr[attr->len++] = data >> 8; - attr->bufptr[attr->len++] = data >> 16; - attr->bufptr[attr->len++] = data >> 24; - } - return attr->len; -} - -size_t buf_add4_be(buf_impl* attr, const uint32_t data) // append 32 bits value -{ - if (attr->len < attr->size - 3) { // do we have room for 4 bytes - attr->bufptr[attr->len++] = data >> 24; - attr->bufptr[attr->len++] = data >> 16; - attr->bufptr[attr->len++] = data >> 8; - attr->bufptr[attr->len++] = data; - } - return attr->len; -} - -static size_t buf_add_buf(buf_impl* attr, buf_impl* attr2) -{ - if (attr->len + attr2->len <= attr->size) { - for (int32_t i = 0; i < attr2->len; i++) { - attr->bufptr[attr->len++] = attr2->bufptr[i]; - } - } - return attr->len; -} - -static size_t buf_add_raw(buf_impl* attr, const void* buf_raw, int32_t len) -{ - uint8_t *buf = (uint8_t*) buf_raw; - if ((len > 0) && (attr->len + len <= attr->size)) { - for (int32_t i = 0; i < len; i++) { - attr->bufptr[attr->len++] = buf[i]; - } - } - return attr->len; -} - -static uint8_t buf_get1(buf_impl* attr, int offset) -{ - if ((offset >= 0) && (offset < attr->len)) { - return attr->bufptr[offset]; - } - return 0; -} - -static void buf_set1(buf_impl* attr, size_t offset, uint8_t data) -{ - if ((int32_t)offset < attr->len) { - attr->bufptr[offset] = data; - } -} - -static void buf_set2_le(buf_impl* attr, size_t offset, uint16_t data) -{ - if ((int32_t)offset + 1 < attr->len) { - attr->bufptr[offset] = data & 0xFF; - attr->bufptr[offset+1] = data >> 8; - } -} - -static void buf_set2_be(buf_impl* attr, size_t offset, uint16_t data) -{ - if ((int32_t)offset + 1 < attr->len) { - attr->bufptr[offset+1] = data & 0xFF; - attr->bufptr[offset] = data >> 8; - } -} - -static uint16_t buf_get2_le(buf_impl* attr, size_t offset) -{ - if ((int32_t)offset + 1 < attr->len) { - return attr->bufptr[offset] | (attr->bufptr[offset+1] << 8); - } - return 0; -} - -static uint16_t buf_get2_be(buf_impl* attr, size_t offset) -{ - if ((int32_t)offset + 1 < attr->len) { - return attr->bufptr[offset+1] | (attr->bufptr[offset] << 8); - } - return 0; -} - -static uint32_t buf_get3_le(buf_impl* attr, size_t offset) -{ - if ((int32_t)offset + 2 < attr->len) { - return attr->bufptr[offset] | (attr->bufptr[offset+1] << 8) | (attr->bufptr[offset+2] << 16); - } - return 0; -} - -static uint32_t buf_get3_be(buf_impl* attr, size_t offset) -{ - if ((int32_t)offset + 2 < attr->len) { - return attr->bufptr[offset+2] | (attr->bufptr[offset+1] << 8) | (attr->bufptr[offset] << 16); - } - return 0; -} - -static void buf_set3_le(buf_impl* attr, size_t offset, uint32_t data) -{ - if ((int32_t)offset + 2 < attr->len) { - attr->bufptr[offset] = data & 0xFF; - attr->bufptr[offset+1] = (data >> 8) & 0xFF; - attr->bufptr[offset+2] = (data >> 16) & 0xFF; - } -} - -static void buf_set3_be(buf_impl* attr, size_t offset, uint32_t data) -{ - if ((int32_t)offset + 2 < attr->len) { - attr->bufptr[offset+2] = data & 0xFF; - attr->bufptr[offset+1] = (data >> 8) & 0xFF; - attr->bufptr[offset] = (data >> 16) & 0xFF; - } -} - -static void buf_set4_le(buf_impl* attr, size_t offset, uint32_t data) -{ - if ((int32_t)offset + 3 < attr->len) { - attr->bufptr[offset] = data & 0xFF; - attr->bufptr[offset+1] = (data >> 8) & 0xFF; - attr->bufptr[offset+2] = (data >> 16) & 0xFF; - attr->bufptr[offset+3] = data >> 24; - } -} - -static void buf_set4_be(buf_impl* attr, size_t offset, uint32_t data) -{ - if ((int32_t)offset + 3 < attr->len) { - attr->bufptr[offset+3] = data & 0xFF; - attr->bufptr[offset+2] = (data >> 8) & 0xFF; - attr->bufptr[offset+1] = (data >> 16) & 0xFF; - attr->bufptr[offset] = data >> 24; - } -} - -static uint32_t buf_get4_le(buf_impl* attr, size_t offset) -{ - if ((int32_t)offset + 3 < attr->len) { - return attr->bufptr[offset] | (attr->bufptr[offset+1] << 8) | - (attr->bufptr[offset+2] << 16) | (attr->bufptr[offset+3] << 24); - } - return 0; -} - -static uint32_t buf_get4_be(buf_impl* attr, size_t offset) -{ - if ((int32_t)offset + 3 < attr->len) { - return attr->bufptr[offset+3] | (attr->bufptr[offset+2] << 8) | - (attr->bufptr[offset+1] << 16) | (attr->bufptr[offset] << 24); - } - return 0; -} - -// nullptr accepted -static bbool buf_equals(buf_impl* buf1, buf_impl* buf2) -{ - if (buf1 == buf2) { return btrue; } - if (!buf1 || !buf2) { return bfalse; } // at least one attr is not empty - // we know that both buf1 and buf2 are non-null - if (buf1->len != buf2->len) { return bfalse; } - size_t len = buf1->len; - if (!buf1->bufptr && !buf2->bufptr) { return btrue; } /* if both are null then considered equal */ - if (!buf1->bufptr || !buf2->bufptr) { return bfalse; } /* if only one is null, then not equal */ - /* here none of the pointer are null */ - for (uint32_t i=0; i= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } - else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; } - return rVal; -} - -// does not check if there is enough room before hand, truncated if buffer too small -static void buf_add_hex(buf_impl* attr, const char *hex, size_t len) -{ - uint8_t val; - for (; len > 1; len -= 2) { - val = asc2byte(*hex++) << 4; - val |= asc2byte(*hex++); - buf_add1(attr, val); - } -} - -/******************************************************************** -** Wrapping into lib -********************************************************************/ - -/* if the bufptr is null, don't try to dereference and raise an exception instead */ -static void check_ptr(bvm *vm, const buf_impl* attr) { - if (!attr->bufptr) { - be_raise(vm, "value_error", "operation not allowed on pointer"); - } -} - -static void check_ptr_modifiable(bvm *vm, const buf_impl* attr) { - if (attr->solidified) { - be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE); - } - if (!attr->bufptr) { - be_raise(vm, "value_error", "operation not allowed on pointer"); - } -} - -/* load instance attribute into a single structure, and store 'previous' values in order to later update only the changed ones */ -/* stack item 1 must contain the instance */ -buf_impl m_read_attributes(bvm *vm, int idx) -{ - buf_impl attr; - be_getmember(vm, idx, ".p"); - attr.bufptr = attr.prev_bufptr = be_tocomptr(vm, -1); - be_pop(vm, 1); - - be_getmember(vm, idx, ".len"); - attr.len = attr.prev_len = be_toint(vm, -1); - be_pop(vm, 1); - - be_getmember(vm, idx, ".size"); - int32_t signed_size = be_toint(vm, -1); - attr.fixed = bfalse; - attr.mapped = bfalse; - attr.solidified = bfalse; - if (signed_size < 0) { - if (signed_size == BYTES_SIZE_MAPPED) { - attr.mapped = btrue; - } - if (signed_size == BYTES_SIZE_SOLIDIFIED) { - attr.solidified = btrue; - } - signed_size = attr.len; - attr.fixed = btrue; - } - attr.size = attr.prev_size = signed_size; - be_pop(vm, 1); - return attr; -} - -static void m_assert_not_readlonly(bvm *vm, const buf_impl* attr) -{ - if (attr->solidified) { - be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE); - } -} - -/* Write back attributes to the bytes instance, only if values changed after loading */ -/* stack item 1 must contain the instance */ -void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr) -{ - m_assert_not_readlonly(vm, attr); - int idx = be_absindex(vm, rel_idx); - if (attr->bufptr != attr->prev_bufptr) { - be_pushcomptr(vm, attr->bufptr); - be_setmember(vm, idx, ".p"); - be_pop(vm, 1); - } - - if (attr->len != attr->prev_len) { - be_pushint(vm, attr->len); - be_setmember(vm, idx, ".len"); - be_pop(vm, 1); - } - - int32_t new_size = attr->size; - if (attr->mapped) { - new_size = BYTES_SIZE_MAPPED; - } else if (attr->fixed) { - new_size = BYTES_SIZE_FIXED; - } - if (new_size != attr->prev_size) { - be_pushint(vm, new_size); - be_setmember(vm, idx, ".size"); - be_pop(vm, 1); - } -} - -// buf_impl * bytes_realloc(bvm *vm, buf_impl *oldbuf, int32_t size) -void bytes_realloc(bvm *vm, buf_impl * attr, size_t size) -{ - m_assert_not_readlonly(vm, attr); - if (!attr->fixed && size < 4) { size = 4; } - if (size > vm->bytesmaxsize) { size = vm->bytesmaxsize; } - size_t oldsize = attr->bufptr ? attr->size : 0; - attr->bufptr = (uint8_t*) be_realloc(vm, attr->bufptr, oldsize, size); /* malloc */ - attr->size = size; - if (!attr->bufptr) { - attr->len = 0; /* allocate a new buffer */ - } -} - -/* allocate a new `bytes` object with pre-allocated size */ -static void bytes_new_object(bvm *vm, size_t size) -{ - be_getbuiltin(vm, "bytes"); - be_pushint(vm, size); - be_call(vm, 1); - be_pop(vm, 1); -} - -/* - * constructor for bytes() - * Arg0 is always self - * - * Option 1: main use - * Arg1: string - a string representing the bytes in HEX - * - * Option 2: - * Arg1: string - a string representing the bytes in HEX - * Arg2: int - pre-reserved buffer size. If negative, size is fixed and cannot be later changed - * - * Option 3: used by subclasses like ctypes - * Arg1: int - pre-reserved buffer size. If negative, size is fixed and cannot be later changed - * - * Option 4: mapped buffer - * Arg1: comptr - buffer address of the mapped buffer - * Arg2: int - buffer size. Always fixed (negative or positive) - * - * */ -static int m_init(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = { 0, 0, NULL, 0, -1, NULL, bfalse, bfalse, bfalse }; /* initialize prev_values to invalid to force a write at the end */ - /* size cannot be 0, len cannot be negative */ - const char * hex_in = NULL; - - int32_t size_arg = 0; - if (argc > 1 && be_isint(vm, 2)) { - size_arg = be_toint(vm, 2); /* raw size arg, can be positive or negative */ - } else if (argc > 2 && be_isint(vm, 3)) { - size_arg = be_toint(vm, 3); /* raw size arg, can be positive or negative */ - } - - if (argc > 1 && be_iscomptr(vm, 2)) { - if (size_arg) { - attr.len = (size_arg < 0) ? -size_arg : size_arg; - attr.bufptr = be_tocomptr(vm, 2); - attr.fixed = btrue; - attr.mapped = btrue; - m_write_attributes(vm, 1, &attr); /* write attributes back to instance */ - be_return_nil(vm); - } else { - be_raise(vm, "value_error", "size is required"); - } - } - if (size_arg == 0) { size_arg = BYTES_DEFAULT_SIZE; } /* if not specified, use default size */ - - /* compute actual size to be reserved */ - if (size_arg >= 0) { - size_arg += BYTES_HEADROOM; /* add automatic headroom to slightly overallocate */ - if (size_arg > attr.size) { - attr.size = size_arg; - } - } else { - attr.size = -size_arg; /* set the size to a fixed negative value */ - attr.fixed = btrue; - } - size_arg = attr.size; - - /* if arg1 is string, we convert hex */ - if (argc > 1 && be_isstring(vm, 2)) { - hex_in = be_tostring(vm, 2); - if (hex_in) { - size_arg = strlen(hex_in) / 2; /* allocate headroom */ - } - /* check if fixed size that we have the right size */ - if (size_arg > attr.size) { - if (attr.fixed) { - be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); - } else { - attr.size = size_arg; - } - } - } - - /* allocate */ - bytes_realloc(vm, &attr, attr.size); /* allocate new buffer */ - if (!attr.bufptr) { - be_throw(vm, BE_MALLOC_FAIL); - } - - if (hex_in) { - buf_add_hex(&attr, hex_in, strlen(hex_in)); - } - - /* if fixed size, set len to size */ - if (attr.fixed) { - buf_set_len(&attr, attr.size); - } - - m_write_attributes(vm, 1, &attr); /* write attributes back to instance */ - be_return_nil(vm); -} - -/* deallocate buffer */ -static int m_deinit(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - if (attr.bufptr != NULL && !attr.mapped) { - be_realloc(vm, attr.bufptr, attr.size, 0); - } - attr.size = 0; - attr.len = 0; - attr.bufptr = NULL; - m_write_attributes(vm, 1, &attr); - be_return_nil(vm); -} - -/* grow or shrink to the exact value */ -/* stack item 1 must contain the instance */ -void _bytes_resize(bvm *vm, buf_impl * attr, size_t new_size) { - bytes_realloc(vm, attr, new_size); - if (!attr->bufptr) { - be_throw(vm, BE_MALLOC_FAIL); - } -} - -/* grow if needed but don't shrink */ -/* if grow, then add some headroom */ -/* stack item 1 must contain the instance */ -void bytes_resize(bvm *vm, buf_impl * attr, size_t new_size) { - if (attr->mapped) { return; } /* if mapped, don't bother with allocation */ - /* when resized to smaller, we introduce a new heurstic */ - /* If the buffer is 64 bytes or smaller, don't shrink */ - /* Shrink buffer only if target size is smaller than half the original size */ - if (attr->size >= (int32_t)new_size) { /* enough room, consider if need to shrink */ - if (attr->size <= 64) { return; } /* don't shrink if below 64 bytes */ - if (attr->size < (int32_t)new_size * 2) { return; } - } - _bytes_resize(vm, attr, new_size); -} - -buf_impl bytes_check_data(bvm *vm, size_t add_size) { - buf_impl attr = m_read_attributes(vm, 1); - /* check if the `size` is big enough */ - if (attr.len + (int32_t)add_size > attr.size) { - if (attr.fixed) { - be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); - } - /* it does not fit so we need to realocate the buffer */ - bytes_resize(vm, &attr, attr.len + add_size); - } - return attr; -} - -size_t be_bytes_tohex(char * out, size_t outsz, const uint8_t * in, size_t insz) { - static const char * hex = "0123456789ABCDEF"; - const uint8_t * pin = in; - char * pout = out; - for (; pin < in + insz; pout += 2, pin++) { - pout[0] = hex[((*pin)>>4) & 0xF]; - pout[1] = hex[ (*pin) & 0xF]; - if (pout + 3 > out + outsz) { break; } /* check overflow */ - } - pout[0] = 0; /* terminating Nul char */ - return pout - out; -} - -static int m_tostring(bvm *vm) -{ - int argc = be_top(vm); - int32_t max_len = 32; /* limit to 32 bytes by default */ - int truncated = 0; - if (argc > 1 && be_isint(vm, 2)) { - max_len = be_toint(vm, 2); /* you can specify the len as second argument, or 0 for unlimited */ - } - buf_impl attr = m_read_attributes(vm, 1); - if (attr.bufptr) { /* pointer looks valid */ - int32_t len = attr.len; - if (max_len > 0 && len > max_len) { - len = max_len; /* limit output size */ - truncated = 1; - } - size_t hex_len = len * 2 + 5 + 2 + 2 + 1 + truncated * 3; /* reserve size for `bytes("")\0` - 9 chars */ - - char * hex_out = be_pushbuffer(vm, hex_len); - size_t l = be_strlcpy(hex_out, "bytes('", hex_len); - l += be_bytes_tohex(&hex_out[l], hex_len - l, attr.bufptr, len); - if (truncated) { - l += be_strlcpy(&hex_out[l], "...", hex_len - l); - } - l += be_strlcpy(&hex_out[l], "')", hex_len - l); - - be_pushnstring(vm, hex_out, l); /* make escape string from buffer */ - be_remove(vm, -2); /* remove buffer */ - } else { /* pointer is null, don't try to dereference it as it would crash */ - be_pushstring(vm, "bytes()"); - } - be_return(vm); -} - -static int m_tohex(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - if (attr.bufptr) { /* pointer looks valid */ - int32_t len = attr.len; - size_t hex_len = len * 2 + 1; - - char * hex_out = be_pushbuffer(vm, hex_len); - size_t l = be_bytes_tohex(hex_out, hex_len, attr.bufptr, len); - - be_pushnstring(vm, hex_out, l); /* make escape string from buffer */ - be_remove(vm, -2); /* remove buffer */ - } else { /* pointer is null, don't try to dereference it as it would crash */ - be_pushstring(vm, ""); - } - be_return(vm); -} - -/* - * Copy the buffer into a string without any changes - */ -static int m_asstring(bvm *vm) -{ - buf_impl attr = bytes_check_data(vm, 0); - check_ptr(vm, &attr); - be_pushnstring(vm, (const char*) attr.bufptr, attr.len); - be_return(vm); -} - -static int m_fromstring(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 2 && be_isstring(vm, 2)) { - const char *s = be_tostring(vm, 2); - int32_t len = be_strlen(vm, 2); /* calling be_strlen to support null chars in string */ - buf_impl attr = bytes_check_data(vm, 0); - check_ptr_modifiable(vm, &attr); - if (attr.fixed && attr.len != len) { - be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); - } - bytes_resize(vm, &attr, len); /* resize if needed */ - if (len > attr.size) { len = attr.size; } /* avoid overflow */ - memmove(attr.bufptr, s, len); - attr.len = len; - be_pop(vm, 1); /* remove arg to leave instance */ - m_write_attributes(vm, 1, &attr); /* update attributes */ - be_return(vm); - } - be_raise(vm, "type_error", "operand must be a string"); - be_return_nil(vm); -} - -/* - * Add an int made of 1, 2 or 4 bytes, in little or big endian - * `add(value:int[, size:int = 1]) -> instance` - * - * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian) - * obvisouly -1 is idntical to 1 - * size==0 does nothing - */ -static int m_add(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */ - check_ptr_modifiable(vm, &attr); - if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } - if (argc >= 2 && be_isint(vm, 2)) { - int32_t v = be_toint(vm, 2); - int vsize = 1; - if (argc >= 3 && be_isint(vm, 3)) { - vsize = be_toint(vm, 3); - } - switch (vsize) { - case 0: break; - case -1: /* fallback below */ - case 1: buf_add1(&attr, v); break; - case 2: buf_add2_le(&attr, v); break; - case 4: buf_add4_le(&attr, v); break; - case -2: buf_add2_be(&attr, v); break; - case -4: buf_add4_be(&attr, v); break; - default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4."); - } - be_pop(vm, argc - 1); - m_write_attributes(vm, 1, &attr); /* update attributes */ - be_return(vm); - } - be_return_nil(vm); -} - -/* - * Get an int made of 1, 2 or 4 bytes, in little or big endian - * `get(index:int[, size:int = 1]) -> int` - * - * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian) - * obvisouly -1 is identical to 1 - * 0 returns nil - */ -static int m_get(bvm *vm, bbool sign) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr(vm, &attr); - if (argc >=2 && be_isint(vm, 2)) { - int32_t idx = be_toint(vm, 2); - int vsize = 1; - if (argc >= 3 && be_isint(vm, 3)) { - vsize = be_toint(vm, 3); - } - if (idx < 0) { - idx = attr.len + idx; /* if index is negative, count from end */ - } - if (idx < 0) { - vsize = 0; /* if still negative, then invalid, return 0 */ - } - int ret = 0; - switch (vsize) { - case 0: break; - case -1: /* fallback below */ - case 1: ret = buf_get1(&attr, idx); - if (sign) { ret = (int8_t)(uint8_t) ret; } - break; - case 2: ret = buf_get2_le(&attr, idx); - if (sign) { ret = (int16_t)(uint16_t) ret; } - break; - case 3: ret = buf_get3_le(&attr, idx); - if (sign & (ret & 0x800000)) { ret = ret | 0xFF000000; } - break; - case 4: ret = buf_get4_le(&attr, idx); break; - case -2: ret = buf_get2_be(&attr, idx); - if (sign) { ret = (int16_t)(uint16_t) ret; } - break; - case -3: ret = buf_get3_be(&attr, idx); - if (sign & (ret & 0x800000)) { ret = ret | 0xFF000000; } - break; - case -4: ret = buf_get4_be(&attr, idx); break; - default: be_raise(vm, "type_error", "size must be -4, -3, -2, -1, 0, 1, 2, 3 or 4."); - } - be_pop(vm, argc - 1); - be_pushint(vm, ret); - be_return(vm); - } - be_return_nil(vm); -} - -/* - * Get a float (32 bits) - * `getfloat(index:int [, big_endian:bool]) -> real` - */ -static int m_getfloat(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr(vm, &attr); - if (argc >=2 && be_isint(vm, 2)) { - int32_t idx = be_toint(vm, 2); - float ret_f = 0; - if (idx < 0) { - idx = attr.len + idx; /* if index is negative, count from end */ - } - if (idx >= 0) { - bbool be = bfalse; /* little endian? */ - if (argc >= 3) { - be = be_tobool(vm, 3); - } - int32_t ret_i = be ? buf_get4_be(&attr, idx) : buf_get4_le(&attr, idx); - ret_f = *(float*) &ret_i; - } - be_pop(vm, argc - 1); - be_pushreal(vm, ret_f); - be_return(vm); - } - be_return_nil(vm); -} - -/* signed int */ -static int m_geti(bvm *vm) -{ - return m_get(vm, 1); -} - -/* unsigned int */ -static int m_getu(bvm *vm) -{ - return m_get(vm, 0); -} - -/* - * Set an int made of 1, 2 or 4 bytes, in little or big endian - * `set(index:int, value:int[, size:int = 1]) -> nil` - * - * size: may be 1, 2, 4 (little endian), or -1, -2, -4 (big endian) - * obvisouly -1 is identical to 1 - * 0 returns nil - */ -static int m_set(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr_modifiable(vm, &attr); - if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) { - int32_t idx = be_toint(vm, 2); - int32_t value = be_toint(vm, 3); - int vsize = 1; - if (argc >= 4 && be_isint(vm, 4)) { - vsize = be_toint(vm, 4); - } - if (idx < 0) { - idx = attr.len + idx; /* if index is negative, count from end */ - } - if (idx < 0) { - vsize = 0; /* if still negative, then invalid, do nothing */ - } - switch (vsize) { - case 0: break; - case -1: /* fallback below */ - case 1: buf_set1(&attr, idx, value); break; - case 2: buf_set2_le(&attr, idx, value); break; - case 3: buf_set3_le(&attr, idx, value); break; - case 4: buf_set4_le(&attr, idx, value); break; - case -2: buf_set2_be(&attr, idx, value); break; - case -3: buf_set3_be(&attr, idx, value); break; - case -4: buf_set4_be(&attr, idx, value); break; - default: be_raise(vm, "type_error", "size must be -4, -3, -2, -1, 0, 1, 2, 3 or 4."); - } - be_pop(vm, argc - 1); - // m_write_attributes(vm, 1, &attr); /* update attributes */ - be_return_nil(vm); - } - be_return_nil(vm); -} - -/* - * Set a 32 bits float - * `setfloat(index:int, value:real or int [, big_endian:bool]) -> nil` - * - */ -static int m_setfloat(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr_modifiable(vm, &attr); - if (argc >=3 && be_isint(vm, 2) && (be_isint(vm, 3) || be_isreal(vm, 3))) { - int32_t idx = be_toint(vm, 2); - if (idx < 0) { - idx = attr.len + idx; /* if index is negative, count from end */ - } - if (idx >= 0) { - float val_f = (float) be_toreal(vm, 3); - int32_t* val_i = (int32_t*) &val_f; - bbool be = bfalse; - if (argc >= 4) { - be = be_tobool(vm, 4); - } - if (be) { buf_set4_be(&attr, idx, *val_i); } else { buf_set4_le(&attr, idx, *val_i); } - be_pop(vm, argc - 1); - // m_write_attributes(vm, 1, &attr); /* update attributes */ - } - be_return_nil(vm); - } - be_return_nil(vm); -} - -/* - * Add a 32 bits float - * `addfloat(value:real or int [, big_endian:bool]) -> instance` - * - */ -static int m_addfloat(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */ - check_ptr_modifiable(vm, &attr); - if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } - if (argc >=2 && (be_isint(vm, 2) || be_isreal(vm, 2))) { - float val_f = (float) be_toreal(vm, 2); - int32_t* val_i = (int32_t*) &val_f; - bbool be = bfalse; - if (argc >= 3) { - be = be_tobool(vm, 3); - } - if (be) { buf_add4_be(&attr, *val_i); } else { buf_add4_le(&attr, *val_i); } - be_pop(vm, argc - 1); - m_write_attributes(vm, 1, &attr); /* update attributes */ - be_return(vm); - } - be_return_nil(vm); -} - -/* - * Fills a buffer with another buffer. - * - * This is meant to be very flexible and avoid loops - * - * `setbytes(index:int, fill:bytes [, from:int, len:int]) -> nil` - * - */ -static int m_setbytes(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr_modifiable(vm, &attr); - if (argc >=3 && be_isint(vm, 2) && (be_isbytes(vm, 3))) { - int32_t idx = be_toint(vm, 2); - size_t from_len_total; - const uint8_t* buf_ptr = (const uint8_t*) be_tobytes(vm, 3, &from_len_total); - if (idx < 0) { - idx = attr.len + idx; /* if index is negative, count from end */ - } - if (idx < 0) { idx = 0; } /* if still negative, start from offset 0 */ - if (idx >= attr.len) { idx = attr.len; } - - int32_t from_byte = 0; - if (argc >= 4 && be_isint(vm, 4)) { - from_byte = be_toint(vm, 4); - if (from_byte < 0) { from_byte = 0; } - if ((size_t)from_byte >= from_len_total) { from_byte = from_len_total; } - } - - int32_t from_len = from_len_total - from_byte; - if (argc >= 5 && be_isint(vm, 5)) { - from_len = be_toint(vm, 5); - if (from_len < 0) { from_len = 0; } - if (from_len >= (int32_t)from_len_total) { from_len = from_len_total; } - } - if (idx + from_len >= attr.len) { from_len = attr.len - idx; } - - // all parameters ok - if (from_len > 0) { - memmove(attr.bufptr + idx, buf_ptr + from_byte, from_len); - } - } - be_return_nil(vm); -} - - -/* - * Reverses in-place a sub-buffer composed of groups of n-bytes packets - * - * This is useful for pixel manipulation when displaying RGB pixels - * - * `reverse([index:int, len:int, grouplen:int]) -> self` - * - */ -static int m_reverse(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr_modifiable(vm, &attr); - - int32_t idx = 0; /* start from index 0 */ - int32_t len = attr.len; /* entire len */ - int32_t grouplen = 1; /* default to 1-byte group */ - - if (argc >= 2 && be_isint(vm, 2)) { - idx = be_toint(vm, 2); - if (idx < 0) { idx = attr.len + idx; } /* if negative, count from end */ - if (idx < 0) { idx = 0; } /* railguards */ - if (idx > attr.len) { idx = attr.len; } - } - if (argc >= 3 && be_isint(vm, 3)) { - len = be_toint(vm, 3); - if (len < 0) { len = attr.len - idx; } /* negative len means */ - } - if (idx + len >= attr.len) { len = attr.len - idx; } - - // truncate len to multiple of grouplen - if (argc >= 4 && be_isint(vm, 4)) { - grouplen = be_toint(vm, 4); - if (grouplen <= 0) { grouplen = 1; } - } - len = len - (len % grouplen); - - // apply reverse - if (len > 0) { - if (grouplen == 1) { - /* fast version if simple byte inversion */ - for (int32_t i = idx, j = idx + len -1; i < j; i++, j--) { - uint8_t temp = attr.bufptr[i]; - attr.bufptr[i] = attr.bufptr[j]; - attr.bufptr[j] = temp; - } - } else { - for (int32_t i = idx, j = idx + len - grouplen; i < j; i += grouplen, j -= grouplen) { - for (int32_t k = 0; k < grouplen; k++) { - uint8_t temp = attr.bufptr[i+k]; - attr.bufptr[i+k] = attr.bufptr[j+k]; - attr.bufptr[j+k] = temp; - } - } - } - } - be_pushvalue(vm, 1); /* push bytes object */ - be_return(vm); -} - -static int m_setitem(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr_modifiable(vm, &attr); - if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) { - int index = be_toint(vm, 2); - int val = be_toint(vm, 3); - if (index < 0) { - index += attr.len; /* if index is negative, count from end */ - } - if (index >= 0 && index < attr.len) { - buf_set1(&attr, index, val); - // m_write_attributes(vm, 1, &attr); /* update attributes */ - be_return_nil(vm); - } - } - be_raise(vm, "index_error", "bytes index out of range or value non int"); - be_return_nil(vm); -} - -static int m_item(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ - check_ptr(vm, &attr); - if (argc >=2 && be_isint(vm, 2)) { /* single byte */ - int index = be_toint(vm,2); - if (index < 0) { - index += attr.len; - } - if (index >= 0 && index < attr.len) { - be_pushint(vm, buf_get1(&attr, index)); - be_return(vm); - } - } - if (argc >= 2 && be_isinstance(vm, 2)) { - const char *cname = be_classname(vm, 2); - if (!strcmp(cname, "range")) { - bint lower, upper; - bint size = attr.len; - /* get index range */ - be_getmember(vm, 2, "__lower__"); - lower = be_toint(vm, -1); - be_pop(vm, 1); - be_getmember(vm, 2, "__upper__"); - upper = be_toint(vm, -1); - be_pop(vm, 1); - /* handle negative limits */ - if (upper < 0) { upper += attr.len; } - if (lower < 0) { lower += attr.len; } - /* protection scope */ - upper = upper < size ? upper : size - 1; - lower = lower < 0 ? 0 : lower; - /* construction result list instance */ - bytes_new_object(vm, upper > lower ? upper-lower : 0); - buf_impl attr2 = m_read_attributes(vm, -1); - - for (; lower <= upper; ++lower) { - buf_add1(&attr2, attr.bufptr[lower]); - } - m_write_attributes(vm, -1, &attr2); /* update instance */ - be_return(vm); - } - } - be_raise(vm, "index_error", "bytes index out of range"); - be_return_nil(vm); -} - -static int m_size(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - be_pushint(vm, attr.len); - be_return(vm); -} - -static int m_tobool(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - be_pushbool(vm, attr.len > 0 ? 1 : 0); - be_return(vm); -} - -static int m_resize(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = m_read_attributes(vm, 1); - check_ptr_modifiable(vm, &attr); - - if (argc <= 1 || !be_isint(vm, 2)) { - be_raise(vm, "type_error", "size must be of type 'int'"); - } - int new_len = be_toint(vm, 2); - if (new_len < 0) { - new_len = 0; - } - if (attr.fixed && attr.len != new_len) { - be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); - } - - bytes_resize(vm, &attr, new_len); - buf_set_len(&attr, new_len); - be_pop(vm, 1); - m_write_attributes(vm, 1, &attr); /* update instance */ - be_return(vm); -} - -static int m_clear(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - check_ptr_modifiable(vm, &attr); - if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } - attr.len = 0; - m_write_attributes(vm, 1, &attr); /* update instance */ - be_return_nil(vm); -} - -static int m_merge(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = m_read_attributes(vm, 1); /* no resize yet */ - check_ptr(vm, &attr); - if (argc >= 2 && (be_isbytes(vm, 2) || be_isstring(vm, 2))) { - const uint8_t * buf; - int32_t buf_len; - if (be_isbytes(vm, 2)) { - buf_impl attr2 = m_read_attributes(vm, 2); - check_ptr(vm, &attr2); - buf = attr2.bufptr; - buf_len = attr2.len; - } else { - buf = (const uint8_t *)be_tostring(vm, 2); - buf_len = strlen((const char *)buf); - } - - /* allocate new object */ - bytes_new_object(vm, attr.len + buf_len); - buf_impl attr3 = m_read_attributes(vm, -1); - check_ptr(vm, &attr3); - - buf_add_buf(&attr3, &attr); - buf_add_raw(&attr3, buf, buf_len); - - m_write_attributes(vm, -1, &attr3); /* update instance */ - be_return(vm); /* return self */ - } - be_raise(vm, "type_error", "operand must be bytes"); - be_return_nil(vm); /* return self */ -} - -static int m_copy(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - check_ptr(vm, &attr); - bytes_new_object(vm, attr.len); - buf_impl attr2 = m_read_attributes(vm, -1); - check_ptr(vm, &attr2); - buf_add_buf(&attr2, &attr); - m_write_attributes(vm, -1, &attr2); /* update instance */ - be_return(vm); /* return self */ -} - -/* accept bytes or int as operand */ -static int m_connect(bvm *vm) -{ - int argc = be_top(vm); - buf_impl attr = m_read_attributes(vm, 1); - check_ptr_modifiable(vm, &attr); - if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } - if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2) || be_isstring(vm, 2))) { - if (be_isint(vm, 2)) { - bytes_resize(vm, &attr, attr.len + 1); /* resize */ - buf_add1(&attr, be_toint(vm, 2)); - m_write_attributes(vm, 1, &attr); /* update instance */ - be_pushvalue(vm, 1); - be_return(vm); /* return self */ - } else if (be_isstring(vm, 2)) { - const char *str = be_tostring(vm, 2); - size_t str_len = strlen(str); - if (str_len > 0) { - bytes_resize(vm, &attr, attr.len + str_len); /* resize */ - buf_add_raw(&attr, str, str_len); - m_write_attributes(vm, 1, &attr); /* update instance */ - } - be_pushvalue(vm, 1); - be_return(vm); /* return self */ - } else { - buf_impl attr2 = m_read_attributes(vm, 2); - check_ptr(vm, &attr2); - bytes_resize(vm, &attr, attr.len + attr2.len); /* resize buf1 for total size */ - buf_add_buf(&attr, &attr2); - m_write_attributes(vm, 1, &attr); /* update instance */ - be_pushvalue(vm, 1); - be_return(vm); /* return self */ - } - } - be_raise(vm, "type_error", "operand must be bytes or int or string"); - be_return_nil(vm); /* return self */ -} - -static int bytes_equal(bvm *vm, bbool iseq) -{ - bbool ret; - buf_impl attr1 = m_read_attributes(vm, 1); - if (!be_isbytes(vm, 2)) { - ret = !iseq; - } else { - buf_impl attr2 = m_read_attributes(vm, 2); - - if (buf_equals(&attr1, &attr2)) { - ret = iseq; - } else { - ret = !iseq; - } - } - be_pushbool(vm, ret); - be_return(vm); -} - -static int m_equal(bvm *vm) -{ - return bytes_equal(vm, btrue); -} - -static int m_nequal(bvm *vm) -{ - return bytes_equal(vm, bfalse); -} - -/* - * Converts bytes() to a base64 string - * - * Note: there are no line breaks inserted - * - * `b.tob64() -> string` - */ -static int m_tob64(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - check_ptr(vm, &attr); - int32_t len = attr.len; - int32_t b64_len = encode_base64_length(len) + 1; /* size of base64 encoded string for this binary length, add NULL terminator */ - - char * b64_out = be_pushbuffer(vm, b64_len); - size_t converted = encode_base64(attr.bufptr, len, (unsigned char*)b64_out); - - be_pushnstring(vm, b64_out, converted); /* make string from buffer */ - be_remove(vm, -2); /* remove buffer */ - be_return(vm); -} - -/* - * Converts base63 to bytes() - * - * `bytes().fromb64() -> bytes()` - */ -static int m_fromb64(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 2 && be_isstring(vm, 2)) { - const char *s = be_tostring(vm, 2); - int32_t bin_len = decode_base64_length((unsigned char*)s); /* do a first pass to calculate the buffer size */ - - buf_impl attr = m_read_attributes(vm, 1); - check_ptr_modifiable(vm, &attr); - if (attr.fixed && attr.len != bin_len) { - be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); - } - bytes_resize(vm, &attr, bin_len); /* resize if needed */ - if (bin_len > attr.size) { /* avoid overflow */ - be_raise(vm, "memory_error", "cannot allocate buffer"); - } - - int32_t bin_len_final = decode_base64((unsigned char*)s, attr.bufptr); /* decode */ - attr.len = bin_len_final; - be_pop(vm, 1); /* remove arg to leave instance */ - m_write_attributes(vm, 1, &attr); /* update instance */ - be_return(vm); - } - be_raise(vm, "type_error", "operand must be a string"); - be_return_nil(vm); -} - -/* - * Converts hex to bytes() - * - * `bytes().fromhexx() -> bytes()` - */ -static int m_fromhex(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 2 && be_isstring(vm, 2)) { - int32_t from = 0; // skip x chars - if (argc >= 3 && be_isint(vm, 3)) { - from = be_toint(vm, 3); - } - const char *s = be_tostring(vm, 2); - int32_t s_len = strlen(s); - if (from < 0) { from = 0; } - if (from > s_len) { from = s_len; } - int32_t bin_len = (s_len - from) / 2; - - buf_impl attr = m_read_attributes(vm, 1); - check_ptr_modifiable(vm, &attr); - if (attr.fixed && attr.len != bin_len) { - be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); - } - bytes_resize(vm, &attr, bin_len); /* resize if needed */ - if (bin_len > attr.size) { /* avoid overflow */ - be_raise(vm, "memory_error", "cannot allocate buffer"); - } - attr.len = 0; - buf_add_hex(&attr, s + from, s_len - from); - - be_pop(vm, 1); /* remove arg to leave instance */ - m_write_attributes(vm, 1, &attr); /* update instance */ - be_pop(vm, be_top(vm) - 1); /* leave instance on stack */ - be_return(vm); - } - be_raise(vm, "type_error", "operand must be a string"); - be_return_nil(vm); -} - -/* - * Advanced API - */ - -/* - * Retrieve the memory address of the raw buffer - * to be used in C functions. - * - * Note: the address is guaranteed not to move unless you - * resize the buffer - * - * `_buffer() -> comptr` - */ -static int m_buffer(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - be_pushcomptr(vm, attr.bufptr); - be_return(vm); -} - -/* - * Returns `btrue` if the buffer is mapped to memory - * or `bfalse` if memory was allocated by us. - * - * `ismapped() -> bool` - */ -static int m_is_mapped(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - bbool mapped = (attr.mapped || (attr.bufptr == NULL)); - be_pushbool(vm, mapped); - be_return(vm); -} - -/* - * Returns `btrue` if the buffer is solidified and read only - * - * `isreadonly() -> bool` - */ -static int m_is_readonly(bvm *vm) -{ - buf_impl attr = m_read_attributes(vm, 1); - be_pushbool(vm, attr.solidified); - be_return(vm); -} - -/* - * Change the pointer to a mapped buffer. - * - * This call does nothing if the buffer is not mapped (i.e. memory is managed externally) - * - * It is typically used to reuse existing Berry object and avoid a complete reallocation - * - * `_change_buffer(comptr) -> comptr` - */ -static int m_change_buffer(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 2 && be_iscomptr(vm, 2)) { - buf_impl attr = m_read_attributes(vm, 1); - if (attr.solidified) { - be_raise(vm, "value_error", BYTES_READ_ONLY_MESSAGE); - } - if (!attr.mapped) { - be_raise(vm, "type_error", "bytes() object must be mapped"); - } - attr.bufptr = be_tocomptr(vm, 2); - m_write_attributes(vm, 1, &attr); /* write attributes back to instance */ - be_pushcomptr(vm, attr.bufptr); - be_return(vm); - } - be_raise(vm, "type_error", "operand must be a comptr"); - be_return_nil(vm); -} - -/* - * External API - */ -BERRY_API void * be_pushbytes(bvm *vm, const void * bytes, size_t len) -{ - bytes_new_object(vm, len); - buf_impl attr = m_read_attributes(vm, -1); - check_ptr(vm, &attr); - if ((int32_t)len > attr.size) { len = attr.size; } /* double check if the buffer allocated was smaller */ - if (bytes) { /* if bytes is null, buffer is filled with zeros */ - memmove((void*)attr.bufptr, bytes, len); - } else { - memset((void*)attr.bufptr, 0, len); - } - attr.len = len; - m_write_attributes(vm, -1, &attr); /* update instance */ - /* bytes instance is on top of stack */ - return (void*)attr.bufptr; -} - -BERRY_API const void *be_tobytes(bvm *vm, int rel_index, size_t *len) -{ - int index = be_absindex(vm, rel_index); - if (be_isbytes(vm, index)) { - buf_impl attr = m_read_attributes(vm, index); - check_ptr(vm, &attr); - if (len) { *len = attr.len; } - return (void*) attr.bufptr; - } - if (len) { *len = 0; } - return NULL; -} - -BERRY_API bbool be_isbytes(bvm *vm, int rel_index) -{ - bbool ret = bfalse; - int index = be_absindex(vm, rel_index); - if (be_isinstance(vm, index)) { - be_getbuiltin(vm, "bytes"); - if (be_isderived(vm, index)) { - ret = btrue; - } - be_pop(vm, 1); - } - return ret; -} - -/* Helper code to compile bytecode - - -class Bytes : bytes -#------------------------------------------------------------- -#- 'getbits' function -#- -#- Reads a bit-field in a `bytes()` object -#- -#- Input: -#- offset_bits (int): bit number to start reading from (0 = LSB) -#- len_bits (int): how many bits to read -#- Output: -#- valuer (int) -#-------------------------------------------------------------# - def getbits(offset_bits, len_bits) - if len_bits <= 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end - var ret = 0 - - var offset_bytes = offset_bits >> 3 - offset_bits = offset_bits % 8 - - var bit_shift = 0 #- bit number to write to -# - - while (len_bits > 0) - var block_bits = 8 - offset_bits # how many bits to read in the current block (block = byte) -# - if block_bits > len_bits block_bits = len_bits end - - var mask = ( (1<> offset_bits) << bit_shift) - - #- move the input window -# - bit_shift += block_bits - len_bits -= block_bits - offset_bits = 0 #- start at full next byte -# - offset_bytes += 1 - end - - return ret - end - - #------------------------------------------------------------- - #- 'setbits' function - #- - #- Writes a bit-field in a `bytes()` object - #- - #- Input: - #- offset_bits (int): bit number to start writing to (0 = LSB) - #- len_bits (int): how many bits to write - #- val (int): value to set - #-------------------------------------------------------------# - def setbits(offset_bits, len_bits, val) - if len_bits < 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end - - val = int(val) #- convert bool or others to int -# - var offset_bytes = offset_bits >> 3 - offset_bits = offset_bits % 8 - - while (len_bits > 0) - var block_bits = 8 - offset_bits #- how many bits to write in the current block (block = byte) -# - if block_bits > len_bits block_bits = len_bits end - - var mask_val = (1<>= block_bits - len_bits -= block_bits - offset_bits = 0 #- start at full next byte -# - offset_bytes += 1 - end - return self - end -end - -*/ - -/******************************************************************** -** Solidified function: getbits -********************************************************************/ -be_local_closure(getbits, /* name */ - be_nested_proto( - 9, /* nstack */ - 3, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str(value_error), - /* K2 */ be_nested_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032), - /* K3 */ be_const_int(3), - /* K4 */ be_const_int(1), - }), - &be_const_str_getbits, - &be_const_str_solidified, - ( &(const binstruction[32]) { /* code */ - 0x180C0500, // 0000 LE R3 R2 K0 - 0x740E0002, // 0001 JMPT R3 #0005 - 0x540E001F, // 0002 LDINT R3 32 - 0x240C0403, // 0003 GT R3 R2 R3 - 0x780E0000, // 0004 JMPF R3 #0006 - 0xB0060302, // 0005 RAISE 1 K1 K2 - 0x580C0000, // 0006 LDCONST R3 K0 - 0x3C100303, // 0007 SHR R4 R1 K3 - 0x54160007, // 0008 LDINT R5 8 - 0x10040205, // 0009 MOD R1 R1 R5 - 0x58140000, // 000A LDCONST R5 K0 - 0x24180500, // 000B GT R6 R2 K0 - 0x781A0011, // 000C JMPF R6 #001F - 0x541A0007, // 000D LDINT R6 8 - 0x04180C01, // 000E SUB R6 R6 R1 - 0x241C0C02, // 000F GT R7 R6 R2 - 0x781E0000, // 0010 JMPF R7 #0012 - 0x5C180400, // 0011 MOVE R6 R2 - 0x381E0806, // 0012 SHL R7 K4 R6 - 0x041C0F04, // 0013 SUB R7 R7 K4 - 0x381C0E01, // 0014 SHL R7 R7 R1 - 0x94200004, // 0015 GETIDX R8 R0 R4 - 0x2C201007, // 0016 AND R8 R8 R7 - 0x3C201001, // 0017 SHR R8 R8 R1 - 0x38201005, // 0018 SHL R8 R8 R5 - 0x300C0608, // 0019 OR R3 R3 R8 - 0x00140A06, // 001A ADD R5 R5 R6 - 0x04080406, // 001B SUB R2 R2 R6 - 0x58040000, // 001C LDCONST R1 K0 - 0x00100904, // 001D ADD R4 R4 K4 - 0x7001FFEB, // 001E JMP #000B - 0x80040600, // 001F RET 1 R3 - }) - ) -); -/*******************************************************************/ - -/******************************************************************** -** Solidified function: setbits -********************************************************************/ -be_local_closure(setbits, /* name */ - be_nested_proto( - 10, /* nstack */ - 4, /* argc */ - 0, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - ( &(const bvalue[ 5]) { /* constants */ - /* K0 */ be_const_int(0), - /* K1 */ be_nested_str(value_error), - /* K2 */ be_nested_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2032), - /* K3 */ be_const_int(3), - /* K4 */ be_const_int(1), - }), - &be_const_str_setbits, - &be_const_str_solidified, - ( &(const binstruction[37]) { /* code */ - 0x14100500, // 0000 LT R4 R2 K0 - 0x74120002, // 0001 JMPT R4 #0005 - 0x5412001F, // 0002 LDINT R4 32 - 0x24100404, // 0003 GT R4 R2 R4 - 0x78120000, // 0004 JMPF R4 #0006 - 0xB0060302, // 0005 RAISE 1 K1 K2 - 0x60100009, // 0006 GETGBL R4 G9 - 0x5C140600, // 0007 MOVE R5 R3 - 0x7C100200, // 0008 CALL R4 1 - 0x5C0C0800, // 0009 MOVE R3 R4 - 0x3C100303, // 000A SHR R4 R1 K3 - 0x54160007, // 000B LDINT R5 8 - 0x10040205, // 000C MOD R1 R1 R5 - 0x24140500, // 000D GT R5 R2 K0 - 0x78160014, // 000E JMPF R5 #0024 - 0x54160007, // 000F LDINT R5 8 - 0x04140A01, // 0010 SUB R5 R5 R1 - 0x24180A02, // 0011 GT R6 R5 R2 - 0x781A0000, // 0012 JMPF R6 #0014 - 0x5C140400, // 0013 MOVE R5 R2 - 0x381A0805, // 0014 SHL R6 K4 R5 - 0x04180D04, // 0015 SUB R6 R6 K4 - 0x541E00FE, // 0016 LDINT R7 255 - 0x38200C01, // 0017 SHL R8 R6 R1 - 0x041C0E08, // 0018 SUB R7 R7 R8 - 0x94200004, // 0019 GETIDX R8 R0 R4 - 0x2C201007, // 001A AND R8 R8 R7 - 0x2C240606, // 001B AND R9 R3 R6 - 0x38241201, // 001C SHL R9 R9 R1 - 0x30201009, // 001D OR R8 R8 R9 - 0x98000808, // 001E SETIDX R0 R4 R8 - 0x3C0C0605, // 001F SHR R3 R3 R5 - 0x04080405, // 0020 SUB R2 R2 R5 - 0x58040000, // 0021 LDCONST R1 K0 - 0x00100904, // 0022 ADD R4 R4 K4 - 0x7001FFE8, // 0023 JMP #000D - 0x80040000, // 0024 RET 1 R0 - }) - ) -); -/*******************************************************************/ - -#if !BE_USE_PRECOMPILED_OBJECT -void be_load_byteslib(bvm *vm) -{ - static const bnfuncinfo members[] = { - { ".p", NULL }, - { ".len", NULL }, - { ".size", NULL }, - { "_buffer", m_buffer }, - { "_change_buffer", m_change_buffer }, - { "ismapped", m_is_mapped }, - { "isreadonly", m_is_readonly }, - { "init", m_init }, - { "deinit", m_deinit }, - { "tostring", m_tostring }, - { "asstring", m_asstring }, - { "tobool", m_tobool }, - { "fromstring", m_fromstring }, - { "tob64", m_tob64 }, - { "fromb64", m_fromb64 }, - { "fromhex", m_fromhex }, - { "tohex", m_tohex }, - { "add", m_add }, - { "get", m_getu }, - { "geti", m_geti }, - { "set", m_set }, - { "seti", m_set }, // setters for signed and unsigned are identical - { "setbytes", m_setbytes }, - { "getfloat", m_getfloat }, - { "setfloat", m_setfloat }, - { "addfloat", m_addfloat }, - { "item", m_item }, - { "setitem", m_setitem }, - { "size", m_size }, - { "resize", m_resize }, - { "clear", m_clear }, - { "reverse", m_reverse }, - { "copy", m_copy }, - { "append", m_connect }, - { "+", m_merge }, - { "..", m_connect }, - { "==", m_equal }, - { "!=", m_nequal }, - - { NULL, (bntvfunc) BE_CLOSURE }, /* mark section for berry closures */ - { "getbits", (bntvfunc) &getbits_closure }, - { "setbits", (bntvfunc) &setbits_closure }, - - { NULL, NULL } - }; - be_regclass(vm, "bytes", members); -} -#else - -#include "../generate/be_const_bytes_def.h" - -/* @const_object_info_begin -class be_class_bytes (scope: global, name: bytes) { - .p, var - .len, var - .size, var - _buffer, func(m_buffer) - _change_buffer, func(m_change_buffer) - ismapped, func(m_is_mapped) - isreadonly, func(m_is_readonly) - init, func(m_init) - deinit, func(m_deinit) - tostring, func(m_tostring) - asstring, func(m_asstring) - tobool, func(m_tobool) - fromstring, func(m_fromstring) - tob64, func(m_tob64) - fromb64, func(m_fromb64) - fromhex, func(m_fromhex) - tohex, func(m_tohex) - add, func(m_add) - get, func(m_getu) - geti, func(m_geti) - getfloat, func(m_getfloat) - setfloat, func(m_setfloat) - addfloat, func(m_addfloat) - set, func(m_set) - seti, func(m_set) - setbytes, func(m_setbytes) - item, func(m_item) - setitem, func(m_setitem) - size, func(m_size) - resize, func(m_resize) - clear, func(m_clear) - reverse, func(m_reverse) - copy, func(m_copy) - append, func(m_connect) - +, func(m_merge) - .., func(m_connect) - ==, func(m_equal) - !=, func(m_nequal) - - getbits, closure(getbits_closure) - setbits, closure(setbits_closure) -} -@const_object_info_end */ -#include "../generate/be_fixed_be_class_bytes.h" -#endif diff --git a/lib/libesp32/Berry/src/be_class.c b/lib/libesp32/Berry/src/be_class.c deleted file mode 100644 index 90c7b5599caf..000000000000 --- a/lib/libesp32/Berry/src/be_class.c +++ /dev/null @@ -1,374 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_class.h" -#include "be_string.h" -#include "be_map.h" -#include "be_exec.h" -#include "be_gc.h" -#include "be_vm.h" -#include "be_func.h" -#include "be_module.h" -#include - -#define check_members(vm, c) \ - if (!(c)->members) { \ - (c)->members = be_map_new(vm); \ - } - -bclass* be_newclass(bvm *vm, bstring *name, bclass *super) -{ - bgcobject *gco = be_gcnew(vm, BE_CLASS, bclass); - bclass *obj = cast_class(gco); - bvalue *buf = be_incrtop(vm); /* protect new objects from GC */ - var_setclass(buf, obj); - if (obj) { - obj->super = super; - obj->members = NULL; /* gc protection */ - obj->nvar = 0; - obj->name = name; - } - be_stackpop(vm, 1); - return obj; -} - -void be_class_compress(bvm *vm, bclass *c) -{ - if (!gc_isconst(c) && c->members) { - be_map_compact(vm, c->members); /* clear space */ - } -} - -/* Return the type of the class attribute, only used to check if the attribute already exists */ -int be_class_attribute(bvm *vm, bclass *c, bstring *attr) -{ - for (; c; c = c->super) { - if (c->members) { - bvalue *v = be_map_findstr(vm, c->members, attr); - if (v) { - return var_type(v); - } - } - } - return BE_NONE; -} - -void be_class_member_bind(bvm *vm, bclass *c, bstring *name, bbool var) -{ - bvalue *attr; - set_fixed(name); - check_members(vm, c); - attr = be_map_insertstr(vm, c->members, name, NULL); - restore_fixed(name); - if (var) { - /* this is an instance variable so we set it as MT_VARIABLE */ - attr->v.i = c->nvar++; - attr->type = MT_VARIABLE; - } else { - /* this is a static class constant, leave it as BE_NIL */ - attr->v.i = 0; - attr->type = BE_NIL; - } -} - -void be_class_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static) -{ - bclosure *cl; - bvalue *attr; - set_fixed(name); - check_members(vm, c); - attr = be_map_insertstr(vm, c->members, name, NULL); - restore_fixed(name); - var_setnil(attr); - cl = be_newclosure(vm, p->nupvals); - cl->proto = p; - var_setclosure(attr, cl); - if (is_static) { - var_markstatic(attr); - } -} - -void be_class_native_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f) -{ - bvalue *attr; - set_fixed(name); - check_members(vm, c); - attr = be_map_insertstr(vm, c->members, name, NULL); - restore_fixed(name); - attr->v.nf = f; - attr->type = MT_PRIMMETHOD; -} - -void be_class_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl) -{ - bvalue *attr; - check_members(vm, c); - attr = be_map_insertstr(vm, c->members, name, NULL); - attr->v.gc = (bgcobject*) cl; - attr->type = MT_METHOD; -} - -/* get the closure method count that need upvalues */ -int be_class_closure_count(bclass *c) -{ - int count = 0; - if (c->members) { - bmapnode *node; - bmap *members = c->members; - bmapiter iter = be_map_iter(); - while ((node = be_map_next(members, &iter)) != NULL) { - if (var_isproto(&node->value)) { - ++count; - } - } - } - return count; -} - -static binstance* instance_member(bvm *vm, - binstance *obj, bstring *name, bvalue *dst) -{ - for (; obj; obj = obj->super) { - bmap *members = obj->_class->members; - if (members) { - bvalue *v = be_map_findstr(vm, members, name); - if (v) { - *dst = *v; - return obj; - } - } - } - var_setnil(dst); - return NULL; -} - -static bclass* class_member(bvm *vm, - bclass *obj, bstring *name, bvalue *dst) -{ - for (; obj; obj = obj->super) { - bmap *members = obj->members; - if (members) { - bvalue *v = be_map_findstr(vm, members, name); - if (v) { - *dst = *v; - return obj; - } - } - } - var_setnil(dst); - return NULL; -} - -void be_class_upvalue_init(bvm *vm, bclass *c) -{ - bmap *mbr = c->members; - if (mbr != NULL) { - bmapnode *node; - bmapiter iter = be_map_iter(); - while ((node = be_map_next(mbr, &iter)) != NULL) { - if (var_isclosure(&node->value)) { - bclosure *cl = var_toobj(&node->value); - if (cl->proto->nupvals) { - /* initialize the closure's upvalues */ - be_release_upvalues(vm, cl); - be_initupvals(vm, cl); - } - } - } - } -} - -/* (internal) Instanciate an instance for a single class and initialize variables to nil */ -static binstance* newobjself(bvm *vm, bclass *c) -{ - size_t size = sizeof(binstance) + sizeof(bvalue) * (c->nvar - 1); - bgcobject *gco = be_newgcobj(vm, BE_INSTANCE, size); - binstance *obj = cast_instance(gco); - be_assert(obj != NULL); - if (obj) { /* initialize members */ - bvalue *v = obj->members, *end = v + c->nvar; /* instance variables is a simple array of pointers at obj->members of size c->nvar */ - while (v < end) { var_setnil(v); ++v; } /* Initialize all instance variables to `nil` */ - obj->_class = c; /* set its class object */ - obj->super = NULL; /* no super class instance for now */ - obj->sub = NULL; /* no subclass instance for now */ - } - return obj; -} - -/* (internal) Instanciate the whole chain of instances when there is a class hierarchy */ -/* All variables set to nil, constructors are not called here */ -static binstance* newobject(bvm *vm, bclass *c) -{ - binstance *obj, *prev; - be_assert(c != NULL); - obj = prev = newobjself(vm, c); - var_setinstance(vm->top, obj); - be_incrtop(vm); /* protect new objects from GC */ - for (c = c->super; c; c = c->super) { /* initialize one instance object per class and per superclass */ - prev->super = newobjself(vm, c); - prev->super->sub = prev; /* link the super/sub classes instances */ - prev = prev->super; - } - be_stackpop(vm, 1); - return obj; -} - -/* Instanciate new instance from stack with argc parameters */ -/* Pushes the constructor on the stack to be executed if a construtor is found */ -/* Returns true if a constructor is found */ -bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode) -{ - bvalue init; - binstance *obj = newobject(vm, c); /* create empty object hierarchy from class hierarchy */ - // reg = vm->reg + pos - mode; /* the stack may have changed, mode=1 when class is instanciated from module #104 */ - var_setinstance(vm->reg + pos, obj); - var_setinstance(vm->reg + pos - mode, obj); /* copy to reg and reg+1 if mode==1 */ - /* find constructor */ - obj = instance_member(vm, obj, str_literal(vm, "init"), &init); - if (obj && var_type(&init) != MT_VARIABLE) { - /* copy argv */ - bvalue * reg; - for (reg = vm->reg + pos + 1; argc > 0; --argc) { - reg[argc] = reg[argc - 2]; - } - *reg = init; /* set constructor */ - return btrue; - } - return bfalse; -} - -/* Find instance member by name and copy value to `dst` */ -/* Do not look into virtual members */ -int be_instance_member_simple(bvm *vm, binstance *instance, bstring *name, bvalue *dst) -{ - int type; - be_assert(name != NULL); - binstance * obj = instance_member(vm, instance, name, dst); - if (obj && var_type(dst) == MT_VARIABLE) { - *dst = obj->members[dst->v.i]; - } - type = var_type(dst); - var_clearstatic(dst); - return type; -} - -/* Find instance member by name and copy value to `dst` */ -/* Input: none of `obj`, `name` and `dst` may not be NULL */ -/* Returns the type of the member or BE_NONE if member not found */ -/* TODO need to support synthetic members */ -int be_instance_member(bvm *vm, binstance *instance, bstring *name, bvalue *dst) -{ - int type; - be_assert(name != NULL); - binstance *obj = instance_member(vm, instance, name, dst); - if (obj && var_type(dst) == MT_VARIABLE) { - *dst = obj->members[dst->v.i]; - } - type = var_type(dst); - if (obj) { - var_clearstatic(dst); - return type; - } else { /* if no method found, try virtual */ - /* if 'init' does not exist, create a virtual empty constructor */ - if (strcmp(str(name), "init") == 0) { - var_setntvfunc(dst, be_default_init_native_function); - return var_primetype(dst); - } else { - /* get method 'member' */ - obj = instance_member(vm, instance, str_literal(vm, "member"), vm->top); - if (obj && basetype(var_type(vm->top)) == BE_FUNCTION) { - bvalue *top = vm->top; - var_setinstance(&top[1], instance); - var_setstr(&top[2], name); - vm->top += 3; /* prevent gc collection results */ - be_dofunc(vm, top, 2); /* call method 'member' */ - vm->top -= 3; - *dst = *vm->top; /* copy result to R(A) */ - if (obj && var_type(dst) == MT_VARIABLE) { - *dst = obj->members[dst->v.i]; - } - type = var_type(dst); - if (type == BE_MODULE) { - /* check if the module is named `undefined` */ - bmodule *mod = var_toobj(dst); - if (strcmp(be_module_name(mod), "undefined") == 0) { - return BE_NONE; /* if the return value is module `undefined`, consider it is an error */ - } - } - var_clearstatic(dst); - return type; - } - } - } - return BE_NONE; -} - -int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst) -{ - int type; - be_assert(name != NULL); - obj = class_member(vm, obj, name, dst); - type = var_type(dst); - var_clearstatic(dst); - return obj ? type : BE_NONE; -} - -bbool be_instance_setmember(bvm *vm, binstance *o, bstring *name, bvalue *src) -{ - bvalue v; - be_assert(name != NULL); - binstance * obj = instance_member(vm, o, name, &v); - if (obj && var_istype(&v, MT_VARIABLE)) { - obj->members[var_toint(&v)] = *src; - return btrue; - } else { - obj = instance_member(vm, o, str_literal(vm, "setmember"), &v); - if (obj && var_type(&v) == MT_VARIABLE) { - v = obj->members[v.v.i]; - } - if (var_basetype(&v) == BE_FUNCTION) { - bvalue *top = vm->top; - var_setval(top, &v); - var_setinstance(top + 1, o); /* move instance to argv[0] */ - var_setstr(top + 2, name); /* move method name to argv[1] */ - var_setval(top + 3, src); /* move method name to argv[1] */ - vm->top += 4; /* prevent collection results */ - be_dofunc(vm, top, 3); /* call method 'member' */ - vm->top -= 4; - /* if return value is `false` or `undefined` signal an unknown attribute */ - int type = var_type(vm->top); - if (type == BE_BOOL) { - bbool ret = var_tobool(vm->top); - if (!ret) { - return bfalse; - } - } else if (type == BE_MODULE) { - /* check if the module is named `undefined` */ - bmodule *mod = var_toobj(vm->top); - if (strcmp(be_module_name(mod), "undefined") == 0) { - return bfalse; /* if the return value is module `undefined`, consider it is an error */ - } - } - return btrue; - } - } - return bfalse; -} - -bbool be_class_setmember(bvm *vm, bclass *o, bstring *name, bvalue *src) -{ - bvalue v; - be_assert(name != NULL); - if (!gc_isconst(o)) { - bclass * obj = class_member(vm, o, name, &v); - if (obj && !var_istype(&v, MT_VARIABLE)) { - be_map_insertstr(vm, obj->members, name, src); - return btrue; - } - } - return bfalse; -} diff --git a/lib/libesp32/Berry/src/be_class.h b/lib/libesp32/Berry/src/be_class.h deleted file mode 100644 index 12f317b5ff40..000000000000 --- a/lib/libesp32/Berry/src/be_class.h +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_CLASS_H -#define BE_CLASS_H - -#include "be_object.h" - -#define MT_VARIABLE BE_INDEX -#define MT_METHOD BE_CLOSURE -#define MT_PRIMMETHOD BE_NTVFUNC - -#define be_class_name(cl) ((cl)->name) -#define be_class_members(cl) ((cl)->members) -#define be_class_super(cl) ((cl)->super) -#define be_class_setsuper(self, sup) ((self)->super = (sup)) -#define be_class_setsub(self, sub) ((self)->sub = (sub)) -#define be_instance_name(obj) ((obj)->_class->name) -#define be_instance_class(obj) ((obj)->_class) -#define be_instance_members(obj) ((obj)->members) -#define be_instance_member_count(obj) ((obj)->_class->nvar) -#define be_instance_super(obj) ((obj)->super) -#define be_instance_sub(obj) ((obj)->sub) - -struct bclass { - bcommon_header; - uint16_t nvar; /* members variable data field count */ - struct bclass *super; - bmap *members; - bstring *name; - bgcobject *gray; /* for gc gray list */ -#ifdef __cplusplus - BE_CONSTEXPR bclass(uint16_t nv, bclass *sup, bmap *mem, bstring *s) : - next(0), type(BE_CLASS), marked(GC_CONST), nvar(nv), - super(sup), members(mem), name(s), gray(0) {} -#endif -}; - -struct binstance { - bcommon_header; - struct binstance *super; - struct binstance *sub; - bclass *_class; - bgcobject *gray; /* for gc gray list */ - bvalue members[1]; /* members variable data field */ -}; - -/* special structure accepting 3 instance variables used only for bytes() solidification */ -struct binstance_arg3 { - bcommon_header; - struct binstance *super; - struct binstance *sub; - bclass *_class; - bgcobject *gray; /* for gc gray list */ - bvalue members[3]; /* members variable data field */ -}; - -bclass* be_newclass(bvm *vm, bstring *name, bclass *super); -void be_class_compress(bvm *vm, bclass *c); -int be_class_attribute(bvm *vm, bclass *c, bstring *attr); -void be_class_member_bind(bvm *vm, bclass *c, bstring *name, bbool var); -void be_class_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static); -void be_class_native_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f); -void be_class_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl); -int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst); -bbool be_class_setmember(bvm *vm, bclass *obj, bstring *name, bvalue *src); -int be_class_closure_count(bclass *c); -void be_class_upvalue_init(bvm *vm, bclass *c); -bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode); -int be_instance_member_simple(bvm *vm, binstance *obj, bstring *name, bvalue *dst); -int be_instance_member(bvm *vm, binstance *obj, bstring *name, bvalue *dst); -bbool be_instance_setmember(bvm *vm, binstance *obj, bstring *name, bvalue *src); - -#endif diff --git a/lib/libesp32/Berry/src/be_code.c b/lib/libesp32/Berry/src/be_code.c deleted file mode 100644 index 9f7cf1300fd3..000000000000 --- a/lib/libesp32/Berry/src/be_code.c +++ /dev/null @@ -1,976 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_code.h" -#include "be_decoder.h" -#include "be_parser.h" -#include "be_lexer.h" -#include "be_vector.h" -#include "be_list.h" -#include "be_var.h" -#include "be_exec.h" -#include "be_vm.h" - -#define NOT_MASK (1 << 0) -#define NOT_EXPR (1 << 1) -#define FUNC_RET_FLAG (1 << 0) - -#define isset(v, mask) (((v) & (mask)) != 0) -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define notexpr(e) isset((e)->not, NOT_EXPR) -#define notmask(e) isset((e)->not, NOT_MASK) -#define exp2anyreg(f, e) exp2reg(f, e, -1) /* -1 means allocate a new register if needed */ -#define var2anyreg(f, e) var2reg(f, e, -1) /* -1 means allocate a new register if needed */ -#define hasjump(e) ((e)->t != (e)->f || notexpr(e)) -#define code_bool(f, r, b, j) codeABC(f, OP_LDBOOL, r, b, j) -#define code_call(f, a, b) codeABC(f, OP_CALL, a, b, 0) -#define code_getmbr(f, a, b, c) codeABC(f, OP_GETMBR, a, b, c) -#define jumpboolop(e, b) ((b) != notmask(e) ? OP_JMPT : OP_JMPF) - -#if BE_USE_SCRIPT_COMPILER - -static int var2reg(bfuncinfo *finfo, bexpdesc *e, int dst); - -#if BE_DEBUG_RUNTIME_INFO -static void codelineinfo(bfuncinfo *finfo) -{ - bvector *vec = &finfo->linevec; - int line = finfo->lexer->lastline; - blineinfo *li = be_vector_end(vec); - if (be_vector_isempty(vec) || li->linenumber != line) { - be_vector_push(finfo->lexer->vm, vec, NULL); - li = be_vector_end(vec); - li->endpc = finfo->pc; - li->linenumber = line; - finfo->proto->lineinfo = be_vector_data(vec); - finfo->proto->nlineinfo = be_vector_capacity(vec); - } else { - li->endpc = finfo->pc; - } -} -#else - #define codelineinfo(finfo) -#endif - -/* Add new instruction in the code vector */ -static int codeinst(bfuncinfo *finfo, binstruction ins) -{ - /* put new instruction in code array */ - be_vector_push_c(finfo->lexer->vm, &finfo->code, &ins); - finfo->proto->code = be_vector_data(&finfo->code); - finfo->proto->codesize = be_vector_capacity(&finfo->code); - codelineinfo(finfo); - return finfo->pc++; -} - -static int codeABC(bfuncinfo *finfo, bopcode op, int a, int b, int c) -{ - return codeinst(finfo, ISET_OP(op) - | ISET_RA(a) | ISET_RKB(b) | ISET_RKC(c)); -} - -static int codeABx(bfuncinfo *finfo, bopcode op, int a, int bx) -{ - return codeinst(finfo, ISET_OP(op) | ISET_RA(a) | ISET_Bx(bx)); -} - -/* Move value from register b to register a */ -/* Check the previous instruction to compact both instruction as one if possible */ -/* If b is a constant, add LDCONST or add MOVE otherwise */ -/* returns false if the move operation happened, or true if there was a register optimization and `b` should be replaced by `a` */ -static bbool code_move(bfuncinfo *finfo, int a, int b) -{ - if (finfo->pc > finfo->binfo->lastjmp) { /* If not the first instruction of the function */ - binstruction *i = be_vector_end(&finfo->code); /* get the last instruction */ - bopcode op = IGET_OP(*i); - if (op <= OP_LDNIL) { /* binop or unop */ - /* remove redundant MOVE instruction */ - int x = IGET_RA(*i), y = IGET_RKB(*i), z = IGET_RKC(*i); - if (b == x && (a == y || (op < OP_NEG && a == z))) { - *i = (*i & ~IRA_MASK) | ISET_RA(a); - return btrue; - } - } - if (!isK(b)) { /* OP_MOVE */ - /* check if the previous OP_MOVE is not identical */ - binstruction mov = ISET_OP(OP_MOVE) | ISET_RA(a) | ISET_RKB(b) | ISET_RKC(0); - if (mov == *i) { - return btrue; /* previous instruction is the same move, remove duplicate */ - } - } - } - if (isK(b)) { - codeABx(finfo, OP_LDCONST, a, b & 0xFF); - } else { - codeABC(finfo, OP_MOVE, a, b, 0); - } - return bfalse; -} - -/* Free register at top (checks that it´s a register) */ -/* Warning: the register must be at top of stack */ -static void free_expreg(bfuncinfo *finfo, bexpdesc *e) -{ - /* release temporary register */ - if (e && e->type == ETREG && e->v.idx == finfo->freereg - 1) { /* free ETREG only if it's top of stack */ - be_code_freeregs(finfo, 1); - } -} - -/* Privat. Allocate `count` new registers on the stack and uptade proto´s max nstack accordingly */ -/* Note: deallocate is simpler and handled by a macro */ -static void allocstack(bfuncinfo *finfo, int count) -{ - int nstack = finfo->freereg + count; - if (nstack > finfo->proto->nstack) { - if (nstack >= 255) { - be_lexerror(finfo->lexer, "register overflow (more than 255)"); - } - finfo->proto->nstack = (bbyte)nstack; - } -} - -/* Allocate `count` registers at top of stack, update stack accordingly */ -int be_code_allocregs(bfuncinfo *finfo, int count) -{ - int base = finfo->freereg; - allocstack(finfo, count); - finfo->freereg += (char)count; - return base; -} - -static void setjump(bfuncinfo *finfo, int pc, int dst) -{ - binstruction *p = be_vector_at(&finfo->code, pc); - int offset = dst - (pc + 1); - /* instruction edit jump destination */ - *p = (*p & ~IBx_MASK) | ISET_sBx(offset); -} - -static int isjumpbool(bfuncinfo *finfo, int pc) -{ - binstruction *p = be_vector_at(&finfo->code, pc); - bopcode op = IGET_OP(*p); - - if (op == OP_JMPT || op == OP_JMPF) { - return 1; - } - return 0; -} - -static int get_jump(bfuncinfo *finfo, int pc) -{ - binstruction *i = be_vector_at(&finfo->code, pc); - int offset = IGET_sBx(*i); - return offset == NO_JUMP ? NO_JUMP : pc + 1 + offset; -} - -static void patchlistaux(bfuncinfo *finfo, int list, int vtarget, int dtarget) -{ - /* mark the last destination point of a jump to avoid false register optimization */ - if (vtarget > finfo->binfo->lastjmp) { - finfo->binfo->lastjmp = vtarget; - } - if (dtarget > finfo->binfo->lastjmp) { - finfo->binfo->lastjmp = dtarget; - } - while (list != NO_JUMP) { - int next = get_jump(finfo, list); - if (isjumpbool(finfo, list)) { - setjump(finfo, list, dtarget); /* jump to default target */ - } else { - setjump(finfo, list, vtarget); - } - list = next; - } -} - -static int appendjump(bfuncinfo *finfo, bopcode op, bexpdesc *e) -{ - int reg = e ? var2anyreg(finfo, e) : 0; - if (isK(reg)) { - reg = be_code_allocregs(finfo, 1); - code_move(finfo, reg, e->v.idx); - e->v.idx = reg; - e->type = ETREG; - } - return codeABx(finfo, op, reg, NO_JUMP + IsBx_MAX); -} - -int be_code_jump(bfuncinfo *finfo) -{ - return appendjump(finfo, OP_JMP, NULL); -} - -void be_code_jumpto(bfuncinfo *finfo, int dst) -{ - be_code_patchlist(finfo, be_code_jump(finfo), dst); -} - -void be_code_jumpbool(bfuncinfo *finfo, bexpdesc *e, int jture) -{ - int pc = appendjump(finfo, jumpboolop(e, jture), e); - be_code_conjump(finfo, jture ? &e->t : &e->f, pc); - be_code_patchjump(finfo, jture ? e->f : e->t); - free_expreg(finfo, e); - jture ? (e->f = NO_JUMP) : (e->t = NO_JUMP); - e->not = 0; -} - -/* connect jump */ -void be_code_conjump(bfuncinfo *finfo, int *list, int jmp) -{ - if (jmp == NO_JUMP) { - return; - } - if (*list == NO_JUMP) { - *list = jmp; - } else { - int next, l = *list; - while ((next = (get_jump(finfo, l))) != NO_JUMP) { - l = next; - } - setjump(finfo, l, jmp); - } -} - -void be_code_patchlist(bfuncinfo *finfo, int list, int dst) -{ - if (dst == finfo->pc) { - be_code_patchjump(finfo, list); - } else { - patchlistaux(finfo, list, dst, dst); - } -} - -void be_code_patchjump(bfuncinfo *finfo, int jmp) -{ - patchlistaux(finfo, jmp, finfo->pc, finfo->pc); -} - -/* Allocate new constant for value k */ -/* If k is NULL then push `nil` value */ -static int newconst(bfuncinfo *finfo, bvalue *k) -{ - int idx = be_vector_count(&finfo->kvec); - be_vector_push_c(finfo->lexer->vm, &finfo->kvec, k); - finfo->proto->ktab = be_vector_data(&finfo->kvec); - finfo->proto->nconst = be_vector_capacity(&finfo->kvec); - if (k == NULL) { - var_setnil(&finfo->proto->ktab[idx]); - } - return idx; -} - -/* Find constant by value and return constant number, or -1 if constant does not exist */ -/* The search is linear and limited to BE_CONST_SEARCH_SIZE elements for performance reasons */ -static int findconst(bfuncinfo *finfo, bexpdesc *e) -{ - int i, count = be_vector_count(&finfo->kvec); - /* if the constant table is too large, the lookup - * operation will become very time consuming. - * so only search the constant table for the - * previous value. - **/ - count = count < BE_CONST_SEARCH_SIZE ? count : BE_CONST_SEARCH_SIZE; - for (i = 0; i < count; ++i) { - bvalue *k = be_vector_at(&finfo->kvec, i); - switch (e->type) { - case ETINT: - if (var_isint(k) && k->v.i == e->v.i) { - return i; - } - break; - case ETREAL: - if (var_isreal(k) && k->v.r == e->v.r) { - return i; - } - break; - case ETSTRING: - if (var_isstr(k) && be_eqstr(k->v.p, e->v.s)) { - return i; - } - break; - default: - break; - } - } - return -1; -} - -/* convert expdesc to constant and return kreg index (either constant kindex or register number) */ -static int exp2const(bfuncinfo *finfo, bexpdesc *e) -{ - int idx = findconst(finfo, e); /* does the constant already exist? */ - if (idx == -1) { /* if not add it */ - bvalue k = {0}; - switch (e->type) { - case ETINT: - k.type = BE_INT; - k.v.i = e->v.i; - break; - case ETREAL: - k.type = BE_REAL; - k.v.r = e->v.r; - break; - case ETSTRING: - k.type = BE_STRING; - k.v.s = e->v.s; - break; - default: /* all other values are filled later */ - break; - } - idx = newconst(finfo, &k); /* create new constant */ - } - if (idx < 256) { /* if constant number fits in KB or KC */ - e->type = ETCONST; /* new type is constant by index */ - e->v.idx = setK(idx); - } else { /* index value is too large */ - e->type = ETREG; /* does not fit in compact mode, allocate an explicit register and emit LDCONTS */ - e->v.idx = be_code_allocregs(finfo, 1); - codeABx(finfo, OP_LDCONST, e->v.idx, idx); - } - return e->v.idx; -} - -static void free_suffix(bfuncinfo *finfo, bexpdesc *e) -{ - int idx = e->v.ss.idx; - int nlocal = be_list_count(finfo->local); - /* release suffix register */ - if (!isK(idx) && idx >= nlocal) { - be_code_freeregs(finfo, 1); - } - /* release object register */ - if (e->v.ss.tt == ETREG && (int)e->v.ss.obj >= nlocal && (e->v.ss.obj + 1 >= finfo->freereg)) { - be_code_freeregs(finfo, 1); - } -} - -static int suffix_destreg(bfuncinfo *finfo, bexpdesc *e1, int dst, bbool no_reg_reuse) -{ - int cand_dst = dst; /* candidate for new dst */ - int nlocal = be_list_count(finfo->local); - int reg1 = (e1->v.ss.tt == ETREG) ? e1->v.ss.obj : -1; /* check if obj is ETREG or -1 */ - int reg2 = (!isK(e1->v.ss.idx) && e1->v.ss.idx >= nlocal) ? e1->v.ss.idx : -1; /* check if idx is ETREG or -1 */ - if (no_reg_reuse) { /* if no_reg_reuse flag, then don't reuse any register, this is useful for compound assignments */ - reg1 = reg2 = -1; - } - - if (reg1 >= 0 && reg2 >= 0) { - /* both are ETREG, we keep the lowest and discard the other */ - if (reg1 != reg2) { - cand_dst = min(reg1, reg2); - be_code_freeregs(finfo, finfo->freereg - cand_dst); /* and free the other one */ - } else { - cand_dst = reg1; /* both ETREG are equal, we return its value */ - } - } else if (reg1 >= 0) { - cand_dst = reg1; - } else if (reg2 >= 0) { - cand_dst = reg2; - } else { - // dst unchanged - } - - if (dst >= finfo->freereg) { - dst = cand_dst; /* if dst was allocating a new register, use the more precise candidate */ - } - return dst; -} - -static int code_suffix(bfuncinfo *finfo, bopcode op, bexpdesc *e, int dst, bbool no_reg_reuse) -{ - dst = suffix_destreg(finfo, e, dst, no_reg_reuse); - if (dst > finfo->freereg) { - dst = finfo->freereg; - } - codeABC(finfo, op, dst, e->v.ss.obj, e->v.ss.idx); - return dst; -} - -/* idx: the proto index in proto_table - * dst: the destination register - **/ -static void code_closure(bfuncinfo *finfo, int idx, int dst) -{ - codeABx(finfo, OP_CLOSURE, dst, idx); /* load closure to register */ -} - -/* Given an integer, check if we should create a constant */ -/* True for values 0..3 and if there is room for kindex */ -/* This optimization makes code more compact for commonly used ints */ -static bbool constint(bfuncinfo *finfo, bint i) -{ - /* cache common numbers */ - if ((i < IsBx_MIN || i > IsBx_MAX) || - (i >= 0 && i <= 3 && be_vector_count(&finfo->kvec) < 256)) { - return btrue; - } - return bfalse; -} - -/* Compute variable from an expdesc */ -/* Return constant index, or existing register or fallback to dst */ -/* At exit, If dst is `freereg`, the register is allocated */ -static int var2reg(bfuncinfo *finfo, bexpdesc *e, int dst) -{ - bbool no_reg_reuse = (dst >= 0); /* if dst reg is explicitly specified, do not optimize register allocation */ - if (dst < 0) { /* if unspecified, allocate a new register if needed */ - dst = finfo->freereg; - } - be_assert(e != NULL); - switch (e->type) { - case ETINT: - if (constint(finfo, e->v.i)) { - return exp2const(finfo, e); - } else { - codeABx(finfo, OP_LDINT, dst, var_toidx(e) + IsBx_MAX); - } - break; - case ETBOOL: - code_bool(finfo, dst, e->v.i != 0, 0); - break; - case ETNIL: - codeABx(finfo, OP_LDNIL, dst, 0); - break; - case ETREAL: - case ETSTRING: - return exp2const(finfo, e); - case ETPROTO: - code_closure(finfo, e->v.idx, dst); - break; - case ETGLOBAL: - codeABx(finfo, OP_GETGBL, dst, e->v.idx); - break; - case ETNGLOBAL: - codeABC(finfo, OP_GETNGBL, dst, e->v.ss.idx, 0); - break; - case ETUPVAL: - codeABx(finfo, OP_GETUPV, dst, e->v.idx); - break; - case ETMEMBER: - dst = code_suffix(finfo, OP_GETMBR, e, dst, no_reg_reuse); - break; - case ETINDEX: - dst = code_suffix(finfo, OP_GETIDX, e, dst, no_reg_reuse); - break; - case ETLOCAL: case ETREG: case ETCONST: - return e->v.idx; - default: - return dst; /* error */ - } - if (dst == finfo->freereg) { /* use a new register */ - be_code_allocregs(finfo, 1); - } - e->type = ETREG; - e->v.idx = dst; - return dst; -} - -static int exp2reg(bfuncinfo *finfo, bexpdesc *e, int dst) -{ - int reg = var2reg(finfo, e, dst); - if (hasjump(e)) { /* if conditional expression */ - int pcf = NO_JUMP; /* position of an eventual LOAD false */ - int pct = NO_JUMP; /* position of an eventual LOAD true */ - int jpt = appendjump(finfo, jumpboolop(e, 1), e); - /* below is a simplified version of `codedestreg` for a single bexpdesc */ - if (e->type == ETREG) { - /* if e is already ETREG from local calculation, we reuse the register */ - reg = e->v.idx; - } else { - /* otherwise, we allocate a new register or use the target provided */ - reg = (dst < 0) ? be_code_allocregs(finfo, 1) : dst; - } - be_code_conjump(finfo, &e->t, jpt); - pcf = code_bool(finfo, reg, 0, 1); - pct = code_bool(finfo, reg, 1, 0); - patchlistaux(finfo, e->f, finfo->pc, pcf); - patchlistaux(finfo, e->t, finfo->pc, pct); - e->t = NO_JUMP; - e->f = NO_JUMP; - e->not = 0; - } - return reg; -} - -/* Select dest registers from both expressions */ -/* If one of them is already a register, keep it */ -/* If e1 or e2 are registers, we keep the lowest and free the highest (that must be at top) */ -/* If none is a register, allocate a new one */ -/* Returns the destination register, guaranteed to be ETREG */ -static int codedestreg(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, int dst) -{ - if (dst < 0) { dst = finfo->freereg; } - int cand_dst = dst; - int con1 = e1->type == ETREG, con2 = e2->type == ETREG; - - if (con1 && con2) { - cand_dst = min(e1->v.idx, e2->v.idx); - be_code_freeregs(finfo, 1); - } else if (con1) { - cand_dst = e1->v.idx; - } else if (con2) { - cand_dst = e2->v.idx; - } else { - if (dst >= finfo->freereg) { - cand_dst = be_code_allocregs(finfo, 1); - return cand_dst; - } - } - if (dst >= finfo->freereg) { - return cand_dst; - } else { - return dst; - } -} - -/* compute binary expression and update e1 as result */ -/* On exit, e1 is guaranteed to be ETREG, which may have been allocated */ -static void binaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e1, bexpdesc *e2, int dst) -{ - int src1 = exp2reg(finfo, e1, dst); /* potentially force the target for src1 reg */ - int src2 = exp2anyreg(finfo, e2); - dst = codedestreg(finfo, e1, e2, dst); - codeABC(finfo, op, dst, src1, src2); - e1->type = ETREG; - e1->v.idx = dst; /* update register as output */ -} - -void be_code_prebinop(bfuncinfo *finfo, int op, bexpdesc *e) -{ - switch (op) { - case OptAnd: - be_code_jumpbool(finfo, e, bfalse); - break; - case OptOr: - be_code_jumpbool(finfo, e, btrue); - break; - default: - exp2anyreg(finfo, e); - break; - } -} - -/* Apply binary operator `op` to e1 and e2, result in e1 */ -void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2, int dst) -{ - switch (op) { - case OptAnd: - var2anyreg(finfo, e2); - be_code_conjump(finfo, &e2->f, e1->f); - *e1 = *e2; - break; - case OptOr: - var2anyreg(finfo, e2); - be_code_conjump(finfo, &e2->t, e1->t); - *e1 = *e2; - break; - case OptAdd: case OptSub: case OptMul: case OptDiv: - case OptMod: case OptLT: case OptLE: case OptEQ: - case OptNE: case OptGT: case OptGE: case OptConnect: - case OptBitAnd: case OptBitOr: case OptBitXor: - case OptShiftL: case OptShiftR: - binaryexp(finfo, (bopcode)(op - OptAdd), e1, e2, dst); - break; - default: break; - } -} - -/* Apply unary operator and return register number */ -/* If input is register, change in place or allocate new register */ -static void unaryexp(bfuncinfo *finfo, bopcode op, bexpdesc *e) -{ - int src = exp2anyreg(finfo, e); - int dst = e->type == ETREG ? src : be_code_allocregs(finfo, 1); - if (!(op == OP_MOVE && src == dst)) { - /* skip if MOVE from same src / dst */ - codeABC(finfo, op, dst, src, 0); - } - e->type = ETREG; - e->v.idx = dst; -} - -/* Apply not to conditional expression */ -/* If literal compute the value */ -/* Or invert t/f subexpressions */ -static void code_not(bfuncinfo *finfo, bexpdesc *e) -{ - switch (e->type) { - case ETINT: e->v.i = e->v.i == 0; break; - case ETREAL: e->v.i = e->v.r == cast(breal, 0); break; - case ETNIL: e->v.i = 1; break; - case ETBOOL: e->v.i = !e->v.i; break; - case ETSTRING: e->v.i = 0; break; - default: { - unaryexp(finfo, OP_MOVE, e); - int temp = e->t; - e->t = e->f; - e->f = temp; - e->not = NOT_EXPR | (e->not ^ NOT_MASK); - return; - } - } - e->type = ETBOOL; -} - -/* Negative value of literal or emit NEG opcode */ -static int code_neg(bfuncinfo *finfo, bexpdesc *e) -{ - switch (e->type) { - case ETINT: e->v.i = -e->v.i; break; - case ETREAL: e->v.r = -e->v.r; break; - case ETNIL: case ETBOOL: case ETSTRING: - return 1; /* error */ - default: - unaryexp(finfo, OP_NEG, e); - } - return 0; -} - -/* Bit flip of literal or emit FLIP opcode */ -static int code_flip(bfuncinfo *finfo, bexpdesc *e) -{ - switch (e->type) { - case ETINT: e->v.i = ~e->v.i; break; - case ETREAL: case ETNIL: case ETBOOL: case ETSTRING: - return 2; /* error */ - default: - unaryexp(finfo, OP_FLIP, e); - } - return 0; -} - -/* Apply unary operator: not, neg or bitflip */ -int be_code_unop(bfuncinfo *finfo, int op, bexpdesc *e) -{ - switch (op) { - case OptNot: - code_not(finfo, e); break; - case OptFlip: /* do nothing */ - return code_flip(finfo, e); - case OptSub: - return code_neg(finfo, e); - default: - break; - } - return 0; -} - -static void setbgblvar(bfuncinfo *finfo, bopcode op, bexpdesc *e1, int src) -{ - if (isK(src)) { /* move const to register */ - code_move(finfo, finfo->freereg, src); - src = finfo->freereg; - } - codeABC(finfo, op, src, e1->v.idx, 0); -} - -static void setsupvar(bfuncinfo *finfo, bopcode op, bexpdesc *e1, int src) -{ - if (isK(src)) { /* move const to register */ - code_move(finfo, finfo->freereg, src); - src = finfo->freereg; - } - codeABx(finfo, op, src, e1->v.idx); -} - -static void setsfxvar(bfuncinfo *finfo, bopcode op, bexpdesc *e1, int src) -{ - int obj = e1->v.ss.obj; - free_suffix(finfo, e1); - if (isK(obj)) { /* move const to register */ - code_move(finfo, finfo->freereg, obj); - obj = finfo->freereg; - } - codeABC(finfo, op, obj, e1->v.ss.idx, src); -} - -/* Assign expr e2 to e1 */ -/* e1 must be in a register and have a valid idx */ -/* if `keep_reg` is true, do not release register */ -/* return 1 if assignment was possible, 0 if type is not compatible */ -int be_code_setvar(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, bbool keep_reg) -{ - /* free_e2 indicates special case where ETINDEX or ETMEMBER need to be freed if top of registers */ - bbool free_e2 = (e2->type == ETINDEX || e2->type == ETMEMBER) && (e2->v.ss.idx != e1->v.idx) && (e2->v.ss.idx == finfo->freereg - 1); - int src = exp2reg(finfo, e2, - e1->type == ETLOCAL ? e1->v.idx : -1); /* Convert e2 to kreg */ - /* If e1 is a local variable, use the register */ - - if (!keep_reg && (e1->type != ETLOCAL || e1->v.idx != src)) { - free_expreg(finfo, e2); /* free source (checks only ETREG) */ /* TODO e2 is at top */ - } else if (!keep_reg && free_e2) { - be_code_freeregs(finfo, 1); - } - switch (e1->type) { - case ETLOCAL: /* It can't be ETREG. */ - if (e1->v.idx != src) { - bbool reg_optimized = code_move(finfo, e1->v.idx, src); /* do explicit move only if needed */ - if (reg_optimized) { - free_expreg(finfo, e2); /* free source (checks only ETREG) */ - *e2 = *e1; /* now e2 is e1 ETLOCAL */ - } - } - break; - case ETGLOBAL: /* store to grobal R(A) -> G(Bx) by global index */ - setsupvar(finfo, OP_SETGBL, e1, src); - break; - case ETNGLOBAL: /* store to global R(A) -> G(Bx) by name */ - setbgblvar(finfo, OP_SETNGBL, e1, src); - break; - case ETUPVAL: - setsupvar(finfo, OP_SETUPV, e1, src); - break; - case ETMEMBER: /* store to member R(A).RK(B) <- RK(C) */ - case ETINDEX: /* store to member R(A)[RK(B)] <- RK(C) */ - setsfxvar(finfo, (e1->type == ETMEMBER) ? OP_SETMBR : OP_SETIDX, e1, src); - if (keep_reg && e2->type == ETREG && e1->v.ss.obj >= be_list_count(finfo->local)) { - /* special case of walrus assignemnt when we need to recreate an ETREG */ - code_move(finfo, e1->v.ss.obj, src); /* move from ETREG to MEMBER instance*/ - free_expreg(finfo, e2); /* free source (checks only ETREG) */ - e2->v.idx = e1->v.ss.obj; /* update to new register */ - } - break; - default: - return 1; - } - return 0; -} - -/* Get the expdesc as a register */ -/* if already in a register, use the existing register */ -/* if local or const, allocate a new register and copy value */ -int be_code_nextreg(bfuncinfo *finfo, bexpdesc *e) -{ - int src = exp2anyreg(finfo, e); /* get variable register index */ - int dst = finfo->freereg; - if ((e->type != ETREG) || (src < dst - 1)) { /* move local and const to new register, don't move if already top of stack */ - code_move(finfo, dst, src); - be_code_allocregs(finfo, 1); - } else { - dst = src; - } - return dst; -} - -int be_code_getmethod(bfuncinfo *finfo, bexpdesc *e) -{ - int dst = finfo->freereg; - be_assert(e->type == ETMEMBER); - dst = code_suffix(finfo, OP_GETMET, e, dst, bfalse); - /* method [object] args */ - be_code_allocregs(finfo, dst == finfo->freereg ? 2 : 1); - return dst; -} - -/* Generate a CALL instruction at base register with argc consecutive values */ -/* i.e. arg1 is base+1... */ -/* Important: argc registers are freed upon call, which are supposed to be registers above base */ -void be_code_call(bfuncinfo *finfo, int base, int argc) -{ - codeABC(finfo, OP_CALL, base, argc, 0); - be_code_freeregs(finfo, argc); -} - -int be_code_proto(bfuncinfo *finfo, bproto *proto) -{ - int idx = be_vector_count(&finfo->pvec); - /* append proto to current function proto table */ - be_vector_push_c(finfo->lexer->vm, &finfo->pvec, &proto); - finfo->proto->ptab = be_vector_data(&finfo->pvec); - finfo->proto->nproto = be_vector_capacity(&finfo->pvec); - return idx; -} - -void be_code_closure(bfuncinfo *finfo, bexpdesc *e, int idx) -{ - int reg = (e->type == ETGLOBAL || e->type == ETNGLOBAL) ? finfo->freereg: e->v.idx; - code_closure(finfo, idx, reg); - if (e->type == ETGLOBAL) { /* store to global R(A) -> G(Bx) */ - codeABx(finfo, OP_SETGBL, reg, e->v.idx); - } else if (e->type == ETNGLOBAL) { /* store R(A) -> GLOBAL[RK(B)] */ - codeABC(finfo, OP_SETNGBL, reg, e->v.idx, 0); - } -} - -void be_code_close(bfuncinfo *finfo, int isret) -{ - bblockinfo *binfo = finfo->binfo; - if (isret) { /* in 'return' */ - while (binfo && !binfo->hasupval) { - binfo = binfo->prev; - } - if (binfo) { - codeABC(finfo, OP_CLOSE, 0, 0, 0); - } - } else if (binfo->prev) { /* leave block */ - if (binfo->hasupval) { - codeABC(finfo, OP_CLOSE, binfo->nactlocals, 0, 0); - } - } -} - -static void leave_function(bfuncinfo *finfo) -{ - int try_depth = 0; /* count of exception catch blocks */ - bblockinfo *binfo = finfo->binfo; - for (; binfo; binfo = binfo->prev) { - if (binfo->type & BLOCK_EXCEPT) { - ++try_depth; /* leave the exception catch block */ - } - } - if (try_depth) { /* exception catch blocks that needs to leave */ - be_code_exblk(finfo, try_depth); - } -} - -void be_code_ret(bfuncinfo *finfo, bexpdesc *e) -{ - if (finfo->binfo->prev == NULL) { - if (finfo->flags & FUNC_RET_FLAG) { - return; - } - finfo->flags |= FUNC_RET_FLAG; - } - if (e) { - int reg = exp2anyreg(finfo, e); - be_code_close(finfo, 1); - leave_function(finfo); - codeABC(finfo, OP_RET, e->type != ETVOID, reg, 0); - free_expreg(finfo, e); - } else { - be_code_close(finfo, 1); - codeABC(finfo, OP_RET, 0, 0, 0); - } -} - -/* Package a suffix object from `c` with key `k` */ -/* Both expdesc are materialized in kregs */ -static void package_suffix(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k) -{ - c->v.ss.obj = exp2anyreg(finfo, c); - int key = exp2anyreg(finfo, k); - c->v.ss.tt = c->type; - c->v.ss.idx = key; -} - -int be_code_nglobal(bfuncinfo *finfo, bexpdesc *k) -{ - return exp2anyreg(finfo, k); -} - -/* Package a MEMBER suffix object from `c` with key `k` */ -void be_code_member(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k) -{ - package_suffix(finfo, c, k); - c->type = ETMEMBER; -} - -/* Package a INDEX suffix object from `c` with key `k` */ -void be_code_index(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k) -{ - package_suffix(finfo, c, k); - c->type = ETINDEX; -} - -void be_code_class(bfuncinfo *finfo, bexpdesc *dst, bclass *c) -{ - int src; - bvalue var = {0}; - var_setclass(&var, c); /* new var of CLASS type */ - src = newconst(finfo, &var); /* allocate a new constant and return kreg */ - if (dst->type == ETLOCAL) { /* if target is a local variable, just assign */ - codeABx(finfo, OP_LDCONST, dst->v.idx, src); - } else if (dst->type == ETGLOBAL) { /* otherwise set as global with same name as class name */ - codeABx(finfo, OP_LDCONST, finfo->freereg, src); - codeABx(finfo, OP_SETGBL, finfo->freereg, dst->v.idx); - } else if (dst->type == ETNGLOBAL) { - codeABx(finfo, OP_LDCONST, finfo->freereg, src); - codeABC(finfo, OP_SETNGBL, finfo->freereg, dst->v.idx, 0); - } - codeABx(finfo, OP_CLASS, 0, src); /* emit CLASS opcode to register class */ -} - -void be_code_setsuper(bfuncinfo *finfo, bexpdesc *c, bexpdesc *s) -{ - int self = exp2anyreg(finfo, c); - int super = exp2anyreg(finfo, s); - codeABC(finfo, OP_SETSUPER, self, super, 0); - free_expreg(finfo, c); - free_expreg(finfo, s); -} - -/* Emit IMPORT opcode for import module */ -/* `m` is module name, is copied to register if not already */ -/* `v` is destination where the imported module is stored */ -/* If destination is a local variable, it is the destination of the IMPORT opcode */ -/* otherwise the value is copied to a temporary register and stored to the destination */ -/* TODO is this optilization useful, isn´t it done anyways by be_code_move optim? */ -void be_code_import(bfuncinfo *finfo, bexpdesc *m, bexpdesc *v) -{ - int dst, src = exp2anyreg(finfo, m); - if (v->type == ETLOCAL) { - dst = v->v.idx; - codeABC(finfo, OP_IMPORT, dst, src, 0); - } else { - dst = be_code_allocregs(finfo, 1); - codeABC(finfo, OP_IMPORT, dst, src, 0); - m->type = ETREG; - m->v.idx = dst; - be_code_setvar(finfo, v, m, bfalse); - } -} - -int be_code_exblk(bfuncinfo *finfo, int depth) -{ - if (depth == 0) { - return appendjump(finfo, OP_EXBLK, NULL); - } - codeABx(finfo, OP_EXBLK, 1, depth); - return 0; -} - -void be_code_catch(bfuncinfo *finfo, int base, int ecnt, int vcnt, int *jmp) -{ - codeABC(finfo, OP_CATCH, base, ecnt, vcnt); - if (jmp) { - *jmp = NO_JUMP; /* reset jump point */ - be_code_conjump(finfo, jmp, be_code_jump(finfo)); - } -} - -/* Emit RAISE opcode */ -/* e1 is the exception code */ -/* e2 is the exception description */ -/* both are materialized to a temp register (if not null) */ -void be_code_raise(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2) -{ - if (e1) { - int src1 = exp2anyreg(finfo, e1); - int src2 = e2 ? exp2anyreg(finfo, e2) : 0; - codeABC(finfo, OP_RAISE, e2 != NULL, src1, src2); - } else { - codeABC(finfo, OP_RAISE, 2, 0, 0); /* rethrow the current exception with parameters already on top of stack */ - } - /* release the register occupied by the expression */ - free_expreg(finfo, e1); - free_expreg(finfo, e2); -} - -void be_code_implicit_class(bfuncinfo *finfo, bexpdesc *e, bclass *c) -{ - bvalue k = {0}; - k.type = BE_CLASS; - k.v.p = c; - int idx = newconst(finfo, &k); /* create new constant */ - e->type = ETCONST; /* new type is constant by index */ - e->v.idx = setK(idx); -} - -#endif diff --git a/lib/libesp32/Berry/src/be_code.h b/lib/libesp32/Berry/src/be_code.h deleted file mode 100644 index f0ef2e1943c8..000000000000 --- a/lib/libesp32/Berry/src/be_code.h +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_CODE_H -#define BE_CODE_H - -#include "be_parser.h" - -#define be_code_freeregs(f, n) ((f)->freereg -= (bbyte)(n)) - -int be_code_allocregs(bfuncinfo *finfo, int count); -void be_code_prebinop(bfuncinfo *finfo, int op, bexpdesc *e); -void be_code_binop(bfuncinfo *finfo, int op, bexpdesc *e1, bexpdesc *e2, int dst); -int be_code_unop(bfuncinfo *finfo, int op, bexpdesc *e); -int be_code_setvar(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2, bbool keep_reg); -int be_code_nextreg(bfuncinfo *finfo, bexpdesc *e); -int be_code_jump(bfuncinfo *finfo); -void be_code_jumpto(bfuncinfo *finfo, int dst); -void be_code_jumpbool(bfuncinfo *finfo, bexpdesc *e, int jumptrue); -void be_code_conjump(bfuncinfo *finfo, int *list, int jmp); -void be_code_patchlist(bfuncinfo *finfo, int list, int dst); -void be_code_patchjump(bfuncinfo *finfo, int jmp); -int be_code_getmethod(bfuncinfo *finfo, bexpdesc *e); -void be_code_call(bfuncinfo *finfo, int base, int argc); -int be_code_proto(bfuncinfo *finfo, bproto *proto); -void be_code_closure(bfuncinfo *finfo, bexpdesc *e, int idx); -void be_code_close(bfuncinfo *finfo, int isret); -void be_code_class(bfuncinfo *finfo, bexpdesc *dst, bclass *c); -void be_code_ret(bfuncinfo *finfo, bexpdesc *e); -int be_code_nglobal(bfuncinfo *finfo, bexpdesc *k); -void be_code_member(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2); -void be_code_index(bfuncinfo *finfo, bexpdesc *c, bexpdesc *k); -void be_code_setsuper(bfuncinfo *finfo, bexpdesc *c, bexpdesc *s); -void be_code_import(bfuncinfo *finfo, bexpdesc *m, bexpdesc *v); -int be_code_exblk(bfuncinfo *finfo, int depth); -void be_code_catch(bfuncinfo *finfo, int base, int ecnt, int vcnt, int *jmp); -void be_code_raise(bfuncinfo *finfo, bexpdesc *e1, bexpdesc *e2); -void be_code_implicit_class(bfuncinfo *finfo, bexpdesc *e, bclass *c); - -#endif diff --git a/lib/libesp32/Berry/src/be_constobj.h b/lib/libesp32/Berry/src/be_constobj.h deleted file mode 100644 index 86a871563110..000000000000 --- a/lib/libesp32/Berry/src/be_constobj.h +++ /dev/null @@ -1,508 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_CONSTOBJ_H -#define BE_CONSTOBJ_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "be_object.h" -#include "be_gc.h" -#include "be_map.h" -#include "be_list.h" -#include "be_class.h" -#include "be_string.h" -#include "be_module.h" -#include "be_byteslib.h" - -#ifndef __cplusplus - -#define be_const_header(_t) \ - .next = NULL, \ - .type = (_t), \ - .marked = GC_CONST - -#define be_define_const_bytes(_name, ...) \ - const binstance_arg3 be_const_instance_##_name = { \ - be_const_header(BE_INSTANCE), \ - .super = NULL, \ - .sub = NULL, \ - ._class = (bclass*) &be_class_bytes, \ - .members = { \ - {.v.c = (const void*) & (const uint8_t[]) { __VA_ARGS__ }, \ - .type = BE_COMPTR }, \ - be_const_int(sizeof(#_name) / 2), \ - be_const_int(BYTES_SIZE_SOLIDIFIED) \ - } \ - } - -/* special version to define a default empty bytes */ -#define be_define_const_bytes_empty() \ - const binstance_arg3 be_const_instance_ = { \ - be_const_header(BE_INSTANCE), \ - .super = NULL, \ - .sub = NULL, \ - ._class = (bclass*) &be_class_bytes, \ - .members = { \ - {.v.c = (const void*) & (const uint8_t[]) { 0x00 }, \ - .type = BE_COMPTR }, \ - be_const_int(0), \ - be_const_int(BYTES_SIZE_SOLIDIFIED) \ - } \ - } - -#define be_const_bytes_instance(_bytes) { \ - .v.c = &be_const_instance_##_bytes, \ - .type = BE_INSTANCE \ -} - -#define be_define_const_str_weak(_name, _s, _len) \ - const bcstring be_const_str_##_name = { \ - .next = NULL, \ - .type = BE_STRING, \ - .marked = GC_CONST, \ - .extra = 0, \ - .slen = _len, \ - .hash = 0, \ - .s = _s \ - } - -#define be_const_key(_str, _next) { \ - .v.c = &be_const_str_##_str, \ - .type = BE_STRING, \ - .next = (uint32_t)(_next) & 0xFFFFFF \ -} - -/* try to use the predefined string in strtab, but don't create an instance if none is present */ -/* the behavior is exactly the same as `be_const_key()` but it not detected by coc */ -#define be_const_key_weak(_str, _next) { \ - .v.c = &be_const_str_##_str, \ - .type = BE_STRING, \ - .next = (uint32_t)(_next) & 0xFFFFFF \ -} - -#define be_const_key_literal(_str, _next) { \ - .v.c = be_str_literal(#_str), \ - .type = BE_STRING, \ - .next = (uint32_t)(_next) & 0xFFFFFF \ -} - -#define be_const_key_int(_i, _next) { \ - .v.i = _i, \ - .type = BE_INT, \ - .next = (uint32_t)(_next) & 0xFFFFFF \ -} - -#define be_const_func(_func) { \ - .v.nf = (_func), \ - .type = BE_NTVFUNC \ -} - -#define be_const_static_func(_func) { \ - .v.nf = (_func), \ - .type = BE_NTVFUNC | BE_STATIC \ -} - -#define be_const_nil() { \ - .v.i = 0, \ - .type = BE_NIL \ -} - -#define be_const_int(_val) { \ - .v.i = (bint)(_val), \ - .type = BE_INT \ -} - -#define be_const_var(_val) { \ - .v.i = (bint)(_val), \ - .type = BE_INDEX \ -} - -#define be_const_real(_val) { \ - .v.r = (breal)(_val), \ - .type = BE_REAL \ -} - -#define be_const_real_hex(_val) { \ - .v.p = (void*)(_val), \ - .type = BE_REAL \ -} - -#define be_const_bool(_val) { \ - .v.b = (bbool)(_val), \ - .type = BE_BOOL \ -} - -#define be_const_str(_str) { \ - .v.s = (bstring*)(_str), \ - .type = BE_STRING \ -} - -#define be_const_comptr(_val) { \ - .v.c = (const void*)(_val), \ - .type = BE_COMPTR \ -} - -#define be_const_class(_class) { \ - .v.c = &(_class), \ - .type = BE_CLASS \ -} - -#define be_const_closure(_closure) { \ - .v.c = &(_closure), \ - .type = BE_CLOSURE \ -} - -#define be_const_static_closure(_closure) { \ - .v.c = &(_closure), \ - .type = BE_CLOSURE | BE_STATIC \ -} - -#define be_const_module(_module) { \ - .v.c = &(_module), \ - .type = BE_MODULE \ -} - -#define be_const_simple_instance(_instance) { \ - .v.c = (_instance), \ - .type = BE_INSTANCE \ -} - -#define be_const_map(_map) { \ - .v.c = &(_map), \ - .type = BE_MAP \ -} - -#define be_const_list(_list) { \ - .v.c = &(_list), \ - .type = BE_LIST \ -} - -#define be_define_const_map_slots(_name) \ -const bmapnode _name##_slots[] = - -#define be_define_const_map(_name, _size) \ -const bmap _name = { \ - be_const_header(BE_MAP), \ - .slots = (bmapnode*)_name##_slots, \ - .lastfree = NULL, \ - .size = _size, \ - .count = _size \ -} - -#define be_define_const_class(_name, _nvar, _super, _name_) \ -const bclass _name = { \ - be_const_header(BE_CLASS), \ - .nvar = _nvar, \ - .super = _super, \ - .members = (bmap*)&_name##_map, \ - .name = (bstring*)&be_const_str_##_name_ \ -} - -#define be_define_const_empty_class(_name, _super, _name_) \ -const bclass _name = { \ - be_const_header(BE_CLASS), \ - .nvar = 0, \ - .super = (bclass*)_super, \ - .members = NULL, \ - .name = (bstring*)&be_const_str_##_name_ \ -} - -#define be_define_const_module(_name, _name_) \ -const bmodule _name = { \ - be_const_header(BE_MODULE), \ - .table = (bmap*)&_name##_map, \ - .info.name = _name_, \ -} - -#define be_define_const_vector(_name, _data, _size) \ -const bvector _name = { \ - .capacity = _size, \ - .size = sizeof(bvalue), \ - .count = _size, \ - .data = (void*)_data, \ - .end = (void*)(_data + (_size) - 1) \ -} - -#define be_define_const_native_module(_module) \ -const bntvmodule_t be_native_module(_module) = { \ - .name = #_module, \ - .attrs = NULL, \ - .size = 0, \ - .module = (bmodule*)&(m_lib##_module) \ -} - -/* defines needed for solidified classes */ -#define be_local_class(_name, _nvar, _super, _map, _cname) \ - const bclass be_class_##_name = { \ - be_const_header(BE_CLASS), \ - .nvar = _nvar, \ - .super = (bclass*)_super, \ - .members = (bmap*)_map, \ - .name = _cname \ -} - -/* defines needed for solidified modules */ -#define be_local_module(_c_name, _module_name, _map) \ - static const bmodule m_lib##_c_name = { \ - be_const_header(BE_MODULE), \ - .table = (bmap*)_map, \ - .info.name = _module_name \ -} - -/* only instances with no super and no sub instance are supported */ -/* primarily for `list` and `map`*/ -#define be_nested_simple_instance(_class_ptr, _members) \ - & (const binstance) { \ - be_const_header(BE_INSTANCE), \ - .super = NULL, \ - .sub = NULL, \ - ._class = (bclass*) _class_ptr, \ - .members = _members \ - } - -#define be_nested_simple_instance_1_arg(_class_ptr, arg0) \ - & (const binstance) { \ - be_const_header(BE_INSTANCE), \ - .super = NULL, \ - .sub = NULL, \ - ._class = (bclass*) _class_ptr, \ - .members = { arg0 } \ - } - - -/* only instances with no super and no sub instance are supported */ -/* primarily for `list` and `map`*/ -#define be_nested_simple_instance_3_args(_class_ptr, arg0, arg1, arg2) \ - & (const binstance_arg3) { \ - be_const_header(BE_INSTANCE), \ - .super = NULL, \ - .sub = NULL, \ - ._class = (bclass*) _class_ptr, \ - .members = { arg0, arg1, arg2 } \ - } - -#define be_nested_map(_size, _slots) \ - & (const bmap) { \ - be_const_header(BE_MAP), \ - .slots = _slots, \ - .lastfree = NULL, \ - .size = _size, \ - .count = _size \ - } - -#define be_nested_list(_size, _items) \ - & (const blist) { \ - be_const_header(BE_LIST), \ - .count = _size, \ - .capacity = _size, \ - .data = _items \ - } - -#define be_nested_str(_name_) \ - { \ - { .s=((bstring*)&be_const_str_##_name_) }, \ - BE_STRING \ - } - -/* variant that does not trigger strtab */ -#define be_nested_str_weak(_name_) \ - { \ - { .s=((bstring*)&be_const_str_##_name_) }, \ - BE_STRING \ - } - -/* variant for long strings that does not trigger strtab */ -#define be_nested_str_long(_name_) \ - { \ - { .s=((bstring*)&be_const_str_##_name_) }, \ - BE_STRING \ - } - -#define be_nested_str_literal(_name_) \ - { \ - { .s=(be_nested_const_str(_name_, _hash, sizeof(_name_)-1 ))\ - }, \ - BE_STRING \ - } - -#define be_str_literal(_str) \ - be_nested_const_str(_str, 0, sizeof(_str)-1 ) - -#define be_str_weak(_str) \ - (bstring*) &be_const_str_##_str - -#define be_nested_string(_str, _hash, _len) \ - { \ - { .s=(be_nested_const_str(_str, _hash, _len )) \ - }, \ - BE_STRING \ - } - -#define be_nested_key(_str, _hash, _len, _next) \ - { \ - { .s=(be_nested_const_str(_str, _hash, _len )) }, \ - BE_STRING, \ - (uint32_t)(_next) & 0xFFFFFF \ - } - -#else - -// #define be_define_const_bytes(_name, ...) \ -// const uint8_t be_const_bin_##_name[] = { __VA_ARGS__ } - -#define be_define_const_str_weak(_name, _s, _len) \ -const bcstring be_const_str_##_name = { \ - NULL, \ - BE_STRING, \ - GC_CONST, \ - 0, \ - _len, \ - 0, \ - _s \ -} - -#define be_const_key(_str, _next) { \ - bvaldata(&be_const_str_##_str), \ - BE_STRING, \ - uint32_t((_next)&0xFFFFFF) \ -} - -/* try to use the predefined string in strtab, but don't create an instance if none is present */ -/* the behavior is exactly the same as `be_const_key()` but it not detected by coc */ -#define be_const_key_weak(_str, _next) { \ - bvaldata(&be_const_str_##_str), \ - BE_STRING, \ - uint32_t((_next)&0xFFFFFF) \ -} - -#define be_const_key_int(_i, _next) { \ - bvaldata(i), \ - BE_INT, \ - uint32_t((_next)&0xFFFFFF) \ -} - -#define be_const_func(_func) { \ - bvaldata(_func), \ - BE_NTVFUNC \ -} - -#define be_const_static_func(_func) { \ - bvaldata(_func), \ - BE_NTVFUNC | BE_STATIC \ -} - -#define be_const_nil() { \ - bvaldata(0), \ - BE_NIL \ -} - -#define be_const_int(_val) { \ - bvaldata(bint(_val)), \ - BE_INT \ -} - -#define be_const_bool(_val) { \ - bvaldata(bbool(_val)), \ - BE_BOOL \ -} - -#define be_const_var(_val) { \ - bvaldata(bint(_val)), \ - BE_INDEX \ -} - -#define be_const_real(_val) { \ - bvaldata(breal(_val)), \ - BE_REAL \ -} - -#define be_const_real_hex(_val) { \ - bvaldata((void*)(_val)), \ - BE_REAL \ -} - -#define be_const_comptr(_val) { \ - bvaldata((void*)(_val)), \ - BE_COMPTR \ -} - -#define be_const_str(_string) { \ - bvaldata(bstring(_string)), \ - BE_STRING \ -} - -#define be_const_class(_class) { \ - bvaldata(&(_class)), \ - BE_CLASS \ -} - -#define be_const_closure(_closure) { \ - bvaldata(&(_closure)), \ - BE_CLOSURE \ -} - -#define be_const_static_closure(_closure) { \ - bvaldata(&(_closure)), \ - BE_CLOSURE | BE_STATIC \ -} - -#define be_const_module(_module) { \ - bvaldata(&(_module)), \ - BE_MODULE \ -} - -#define be_define_const_map_slots(_name) \ -const bmapnode _name##_slots[] = - -#define be_define_const_map(_name, _size) \ -const bmap _name( \ - (bmapnode*)_name##_slots, _size \ -) - -#define be_define_const_class(_name, _nvar, _super, _name_) \ -const bclass _name( \ - _nvar, (bclass*)_super, (bmap*)&_name##_map, \ - (bstring*)&be_const_str_##_name_ \ -) - -#define be_define_const_empty_class(_name, _super, _name_) \ -const bclass _name( \ - 0, (bclass*)_super, NULL, \ - (bstring*)&be_const_str_##_name_ \ -) - -#define be_define_const_module(_name, _name_) \ -const bmodule _name((bmap*)&_name##_map, _name_) - -#define be_define_const_vector(_name, _data, _size) \ -const bvector _name = { \ - _size, sizeof(bvalue), _size, \ - (void*)_data, (void*)(_data + (_size) - 1) \ -} - -#define be_define_const_native_module(_module) \ -const bntvmodule_t be_native_module_##_module = { \ - #_module, \ - 0, 0, \ - (bmodule*)&(m_lib##_module) \ -} - -#endif - -/* provide pointers to map and list classes for solidified code */ -extern const bclass be_class_list; -extern const bclass be_class_map; -extern const bclass be_class_bytes; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32/Berry/src/be_debug.c b/lib/libesp32/Berry/src/be_debug.c deleted file mode 100644 index 142c4ea5eab4..000000000000 --- a/lib/libesp32/Berry/src/be_debug.c +++ /dev/null @@ -1,418 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_debug.h" -#include "be_func.h" -#include "be_decoder.h" -#include "be_string.h" -#include "be_class.h" -#include "be_vm.h" -#include "be_vector.h" -#include "be_strlib.h" -#include "be_exec.h" -#include "be_mem.h" -#include "be_sys.h" -#include -#include - -#if BE_USE_DEBUG_HOOK && !BE_DEBUG_RUNTIME_INFO - #error This macro BE_USE_DEBUG_HOOK requires BE_DEBUG_RUNTIME_INFO != 0 -#endif - -#ifndef INST_BUF_SIZE -#define INST_BUF_SIZE 96 -#endif - -#define logbuf(...) snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__) - -#define logfmt(...) \ - do { \ - char __lbuf[INST_BUF_SIZE]; \ - logbuf(__VA_ARGS__); \ - be_writestring(__lbuf); \ - } while (0) - -#if BE_USE_DEBUG_MODULE -static const char* opc2str(bopcode op) -{ - static const char* const opc_tab[] = { - #define OPCODE(opc) #opc - #include "be_opcodes.h" - #undef OPCODE - }; - return op < array_count(opc_tab) ? opc_tab[op] : "ERROP"; -} - -void be_print_inst(binstruction ins, int pc, void* fout) -{ - char __lbuf[INST_BUF_SIZE + 1], __lbuf_tmp[INST_BUF_SIZE]; - bopcode op = IGET_OP(ins); - - logbuf(" %.4X ", pc); - if (fout) { - be_fwrite(fout, __lbuf, strlen(__lbuf)); - } else { - be_writestring(__lbuf); - } - switch (op) { - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: - case OP_MOD: case OP_LT: case OP_LE: case OP_EQ: - case OP_NE: case OP_GT: case OP_GE: case OP_CONNECT: - case OP_GETMBR: case OP_SETMBR: case OP_GETMET: - case OP_GETIDX: case OP_SETIDX: case OP_AND: - case OP_OR: case OP_XOR: case OP_SHL: case OP_SHR: - logbuf("%s\tR%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins), - isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK, - isKC(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK); - break; - case OP_GETNGBL: case OP_SETNGBL: - logbuf("%s\tR%d\t%c%d", opc2str(op), IGET_RA(ins), - isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK); - break; - case OP_GETGBL: case OP_SETGBL: - logbuf("%s\tR%d\tG%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins)); - break; - case OP_MOVE: case OP_SETSUPER: case OP_NEG: case OP_FLIP: case OP_IMPORT: - logbuf("%s\tR%d\t%c%d", opc2str(op), IGET_RA(ins), - isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK); - break; - case OP_JMP: - logbuf("%s\t\t#%.4X", opc2str(op), IGET_sBx(ins) + pc + 1); - break; - case OP_JMPT: case OP_JMPF: - logbuf("%s\tR%d\t#%.4X", opc2str(op), IGET_RA(ins), IGET_sBx(ins) + pc + 1); - break; - case OP_LDINT: - logbuf("%s\tR%d\t%d", opc2str(op), IGET_RA(ins), IGET_sBx(ins)); - break; - case OP_LDBOOL: - logbuf("%s\tR%d\t%d\t%d", opc2str(op), IGET_RA(ins), IGET_RKB(ins), IGET_RKC(ins)); - break; - case OP_RET: - if (IGET_RA(ins)) { - logbuf("%s\t%d\t%c%d", opc2str(op), IGET_RA(ins), - isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK); - } else { - logbuf("%s\t%d", opc2str(op), IGET_RA(ins)); /* RET 0 does not take an additional parameter */ - } - break; - case OP_GETUPV: case OP_SETUPV: - logbuf("%s\tR%d\tU%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins)); - break; - case OP_LDCONST: - logbuf("%s\tR%d\tK%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins)); - break; - case OP_CALL: - logbuf("%s\tR%d\t%d", opc2str(op), IGET_RA(ins), IGET_RKB(ins)); - break; - case OP_CLOSURE: - logbuf("%s\tR%d\tP%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins)); - break; - case OP_CLASS: - logbuf("%s\tK%d", opc2str(op), IGET_Bx(ins)); - break; - case OP_CLOSE: case OP_LDNIL: - logbuf("%s\tR%d", opc2str(op), IGET_RA(ins)); - break; - case OP_RAISE: - logbuf("%s\t%d\t%c%d\t%c%d", opc2str(op), IGET_RA(ins), - isKB(ins) ? 'K' : 'R', IGET_RKB(ins) & KR_MASK, - isKC(ins) ? 'K' : 'R', IGET_RKC(ins) & KR_MASK); - break; - case OP_EXBLK: - if (IGET_RA(ins)) { - logbuf("%s\t%d\t%d", opc2str(op), IGET_RA(ins), IGET_Bx(ins)); - } else { - logbuf("%s\t%d\t#%.4X", opc2str(op), IGET_RA(ins), IGET_sBx(ins) + pc + 1); - } - break; - case OP_CATCH: - logbuf("%s\tR%d\t%d\t%d", opc2str(op), IGET_RA(ins), IGET_RKB(ins), IGET_RKC(ins)); - break; - default: - logbuf("%s", opc2str(op)); - break; - } - memcpy(__lbuf_tmp, __lbuf, strlen(__lbuf) + 1); - logbuf("%s\n", __lbuf_tmp); - if (fout) { - be_fwrite(fout, __lbuf, strlen(__lbuf)); - } else { - be_writestring(__lbuf); - } -} -#endif - -#if BE_USE_DEBUG_MODULE -void be_dumpclosure(bclosure *cl) -{ - int pc; - bproto *proto = cl->proto; - binstruction *code = proto->code; -#if BE_DEBUG_RUNTIME_INFO - blineinfo *lineinfo = proto->lineinfo; -#endif -#if BE_DEBUG_SOURCE_FILE - logfmt("source '%s', ", str(proto->source)); -#endif - logfmt("function '%s':\n", str(proto->name)); -#if BE_DEBUG_RUNTIME_INFO - if (lineinfo) { /* first line */ - logfmt("; line %d\n", lineinfo->linenumber); - } -#endif - for (pc = 0; pc < proto->codesize; pc++) { -#if BE_DEBUG_RUNTIME_INFO - if (lineinfo && pc > lineinfo->endpc) { - logfmt("; line %d\n", (++lineinfo)->linenumber); - } -#endif - be_print_inst(*code++, pc, NULL); - } -} -#endif - -static void sourceinfo(bproto *proto, binstruction *ip) -{ -#if BE_DEBUG_RUNTIME_INFO - char buf[24]; - be_assert(proto != NULL); - if (proto->lineinfo && proto->nlineinfo) { - blineinfo *it = proto->lineinfo; - blineinfo *end = it + proto->nlineinfo; - int pc = cast_int(ip - proto->code - 1); /* now vm->ip has been increased */ - for (; it < end && pc > it->endpc; ++it); - snprintf(buf, sizeof(buf), ":%d:", it->linenumber); -#if BE_DEBUG_SOURCE_FILE - be_writestring(str(proto->source)); -#endif - be_writestring(buf); - } else { - be_writestring(":"); - } -#else - (void)proto; (void)ip; - be_writestring(":"); -#endif -} - -static void tracestack(bvm *vm) -{ - bcallsnapshot *cf; - bcallsnapshot *base = be_stack_base(&vm->tracestack); - bcallsnapshot *top = be_stack_top(&vm->tracestack); - be_writestring("stack traceback:\n"); - for (cf = top; cf >= base; --cf) { - if (cf <= top - 10 && cf >= base + 10) { - if (cf == top - 10) - be_writestring("\t...\n"); - continue; - } - if (var_isclosure(&cf->func)) { - bclosure *cl = var_toobj(&cf->func); - be_writestring("\t"); - sourceinfo(cl->proto, cf->ip); - be_writestring(" in function `"); - be_writestring(str(cl->proto->name)); - be_writestring("`\n"); - } else { - be_writestring("\t: in native function\n"); - } - } -} - -static void repair_stack(bvm *vm) -{ - bcallsnapshot *cf; - bcallsnapshot *base = be_stack_base(&vm->tracestack); - bcallsnapshot *top = be_stack_top(&vm->tracestack); - /* Because the native function does not push `ip` to the - * stack, the ip on the native function frame corresponds - * to the previous Berry closure. */ - for (cf = top; cf >= base; --cf) { - if (!var_isclosure(&cf->func)) { - /* the last native function stack frame has the `ip` of - * the previous Berry frame */ - binstruction *ip = cf->ip; - /* skip native function stack frames */ - for (; cf >= base && !var_isclosure(&cf->func); --cf); - /* fixed `ip` of Berry closure frame near native function frame */ - if (cf >= base) cf->ip = ip; - } - } -} - -void be_tracestack(bvm *vm) -{ - if (be_stack_count(&vm->tracestack)) { - repair_stack(vm); - tracestack(vm); - } -} - -#if BE_USE_DEBUG_HOOK - -static void hook_callnative(bvm *vm, int mask) -{ - bhookinfo_t info; - int top = be_top(vm); - bcallframe *cf = vm->cf; - bclosure *cl = var_toobj(cf->func); - struct bhookblock *hb = var_toobj(&vm->hook); - be_stack_require(vm, BE_STACK_FREE_MIN + 2); - info.type = mask; - info.line = cf->lineinfo->linenumber; -#if BE_DEBUG_SOURCE_FILE - info.source = str(cl->proto->source); -#endif - info.func_name = str(cl->proto->name); - info.data = hb->data; - hb->hook(vm, &info); - vm->top += 2; - be_pop(vm, be_top(vm) - top); -} - -static int hook_pushargs(bvm *vm, int mask) -{ - bcallframe *cf = vm->cf; - if (mask == BE_HOOK_LINE) { - be_pushstring(vm, "line"); - be_pushint(vm, cf->lineinfo->linenumber); - return 2; - } - if (mask == BE_HOOK_CALL) { - bclosure *cl = var_toobj(cf->func); - be_pushstring(vm, "call"); - var_setstr(vm->top, cl->proto->name); - vm->top++; - return 2; - } - if (mask == BE_HOOK_RET) { - be_pushstring(vm, "return"); - return 1; - } - return 0; -} - -static void hook_call(bvm *vm, int mask) -{ - int argc; - vm->top[2] = vm->hook; - be_stack_require(vm, 5); - vm->top += 3; - argc = hook_pushargs(vm, mask); - be_call(vm, argc); - be_pop(vm, 3 + argc); -} - -void be_callhook(bvm *vm, int mask) -{ - if (vm->hookmask & mask) { - int hookmask = vm->hookmask; - vm->hookmask = 0; - if (var_istype(&vm->hook, BE_COMPTR)) { - hook_callnative(vm, mask); - } else { - hook_call(vm, mask); - } - vm->hookmask = (bbyte)hookmask; - } -} - -static bbyte parse_hookmask(const char *mask) -{ - int c, res = 0; - if (mask) { - while ((c = *mask++) != '\0') { - switch (c) { - case 'l': res |= BE_HOOK_LINE; break; - case 'c': res |= BE_HOOK_CALL; break; - case 'r': res |= BE_HOOK_RET; break; - default: break; - } - } - } - return (bbyte)res; -} - -BERRY_API void be_sethook(bvm *vm, const char *mask) -{ - vm->hookmask = parse_hookmask(mask); - if (vm->hookmask && var_istype(&vm->hook, BE_COMPTR)) /* free native hook */ - be_free(vm, var_toobj(&vm->hook), sizeof(struct bhookblock)); - if (vm->hookmask) { - vm->hook = *be_indexof(vm, -1); - } else if (!var_istype(&vm->hook, BE_COMPTR)) { - var_setnil(&vm->hook); - } -} - -BERRY_API void be_setntvhook(bvm *vm, bntvhook hook, void *data, int mask) -{ - struct bhookblock *hb; - if (mask) { - if (!var_istype(&vm->hook, BE_COMPTR)) { - var_setobj(&vm->hook, BE_COMPTR, - be_malloc(vm, sizeof(struct bhookblock))); - } - hb = var_toobj(&vm->hook); - be_assert(hb != NULL); - hb->hook = hook; - hb->data = data; - } else if (!var_istype(&vm->hook, BE_COMPTR)) { - var_setnil(&vm->hook); - } - vm->hookmask = (bbyte)mask; -} - -#endif - -#if BE_DEBUG_VAR_INFO -static binstruction* callstack_fixip(bvm *vm, int level) -{ - bcallframe *top = (bcallframe*)be_stack_top(&vm->callstack); - bcallframe *cf = top - level + 2; - for (; cf <= top && cf->status & PRIM_FUNC; ++cf); - return cf <= top ? cf->ip : vm->ip; -} - -bbool be_debug_varname(bvm *vm, int level, int index) -{ - int depth = be_stack_count(&vm->callstack); - if (level > 0 && level <= depth) { - bcallframe *cf = be_vector_at(&vm->callstack, depth - level); - if ((cf->status & PRIM_FUNC) == 0) { - bproto *proto = cast(bclosure*, var_toobj(cf->func))->proto; - int pc = (int)(callstack_fixip(vm, level) - proto->code); - bstring *name = be_func_varname(proto, index, pc); - if (name) { - bvalue *reg = be_incrtop(vm); - var_setstr(reg, name); - return btrue; - } - } - } - return bfalse; -} - -bbool be_debug_upvname(bvm *vm, int level, int index) -{ - int depth = be_stack_count(&vm->callstack); - if (level > 0 && level <= depth) { - bcallframe *cf = be_vector_at(&vm->callstack, depth - level); - if ((cf->status & PRIM_FUNC) == 0) { - bproto *proto = cast(bclosure*, var_toobj(cf->func))->proto; - if (index >= 0 && index < proto->nupvals) { - bvalue *reg = be_incrtop(vm); - var_setstr(reg, proto->upvals[index].name); - return btrue; - } - } - } - return bfalse; -} -#endif diff --git a/lib/libesp32/Berry/src/be_debug.h b/lib/libesp32/Berry/src/be_debug.h deleted file mode 100644 index b8e2edf4b641..000000000000 --- a/lib/libesp32/Berry/src/be_debug.h +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_DEBUG_H -#define BE_DEBUG_H - -#include "be_object.h" - -struct bhookblock { - void *data; - bntvhook hook; -}; - -void be_dumpclosure(bclosure *cl); -void be_tracestack(bvm *vm); -void be_callhook(bvm *vm, int mask); -bbool be_debug_varname(bvm *vm, int level, int index); -bbool be_debug_upvname(bvm *vm, int level, int index); - -#if BE_USE_DEBUG_MODULE -void be_print_inst(binstruction ins, int pc, void* fout); -#endif - -#endif diff --git a/lib/libesp32/Berry/src/be_debuglib.c b/lib/libesp32/Berry/src/be_debuglib.c deleted file mode 100644 index 2e4ee9bf41a7..000000000000 --- a/lib/libesp32/Berry/src/be_debuglib.c +++ /dev/null @@ -1,289 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_module.h" -#include "be_string.h" -#include "be_vector.h" -#include "be_class.h" -#include "be_debug.h" -#include "be_map.h" -#include "be_vm.h" -#include "be_exec.h" -#include - -#if BE_USE_DEBUG_MODULE - -static void dump_map(bmap *map) -{ - bmapnode *node; - bmapiter iter = be_map_iter(); - while ((node = be_map_next(map, &iter)) != NULL) { - if (var_isstr(&node->key)) { - bstring *s = var_tostr(&node->key); - be_writestring("\t"); - be_writebuffer(str(s), str_len(s)); - be_writestring(": <"); - be_writestring(be_vtype2str(&node->value)); - be_writestring(">\n"); - } - } -} - -static void dump_module(bmodule *module) -{ - dump_map(module->table); -} - -static void dump_class(bclass *class) -{ - if (class->members) { - dump_map(class->members); - } -} - -static void dump_instanse(binstance *ins) -{ - dump_class(ins->_class); -} - -static void dump_value(bvalue *value) -{ - be_writestring("value type <"); - be_writestring(be_vtype2str(value)); - be_writestring(">, attributes:\n"); -} - -static int m_attrdump(bvm *vm) -{ - if (be_top(vm) >= 1) { - bvalue *v = be_indexof(vm, 1); - void *obj = var_toobj(v); - dump_value(v); - switch (var_type(v)) { - case BE_MODULE: dump_module(obj); break; - case BE_CLASS: dump_class(obj); break; - case BE_INSTANCE: dump_instanse(obj); break; - default: break; - } - } - be_return_nil(vm); -} - -static int m_codedump(bvm *vm) -{ - if (be_top(vm) >= 1) { - bvalue *v = be_indexof(vm, 1); - if (var_isclosure(v)) { - be_dumpclosure(var_toobj(v)); - } - } - be_return_nil(vm); -} - -static int m_gcdebug(bvm *vm) { - int argc = be_top(vm); - if (argc >= 1 && be_isbool(vm, 1)) { - if (be_tobool(vm, 1)) { - comp_set_gc_debug(vm); - } else { - comp_clear_gc_debug(vm); - } - } - be_pushbool(vm, comp_is_gc_debug(vm)); - be_return(vm); -} - -static int m_traceback(bvm *vm) -{ - be_tracestack(vm); - be_return_nil(vm); -} - -static int m_caller(bvm *vm) -{ - int depth = 1; - if (be_top(vm) >= 1 && be_isint(vm, 1)) { - depth = be_toint(vm, 1); - if (depth < 0) { - depth = -depth; /* take absolute value */ - } - } - bcallframe *cf = (bcallframe*)be_stack_top(&vm->callstack) - depth; - bcallframe *base = be_stack_base(&vm->callstack); - if (cf >= base) { - bvalue *reg = be_incrtop(vm); - var_setval(reg, cf->func); - be_return(vm); - } else { - be_return_nil(vm); - } -} - -#if BE_USE_DEBUG_HOOK -static int m_sethook(bvm *vm) -{ - if (be_top(vm) >= 2) { - be_pushvalue(vm, 1); - be_sethook(vm, be_tostring(vm, 2)); - } else { - be_sethook(vm, NULL); - } - be_return_nil(vm); -} -#endif - -static int m_top(bvm *vm) -{ - bint top = vm->top - vm->stack + 1; - be_pushint(vm, top); - be_return(vm); -} - -static int m_calldepth(bvm *vm) -{ - bint depth = be_stack_count(&vm->callstack); - be_pushint(vm, depth); - be_return(vm); -} - -#if BE_DEBUG_VAR_INFO -static int v_getname(bvm *vm, bbool(*getter)(bvm *vm, int, int)) -{ - int index, level = 1; - if (be_top(vm) < 1) - be_raise(vm, "value_error", "too few arguments"); - if (!be_isint(vm, 1) || (be_top(vm) >= 2 && !be_isint(vm, 2))) - be_raise(vm, "value_error", "invalid argument(s) value"); - if (be_top(vm) >= 2) - level = be_toindex(vm, 2); - index = be_toindex(vm, 1); - if (index < 0) - be_raise(vm, "value_error", "variable index cannot be less than 0"); - if (level < 1 || level >= be_stack_count(&vm->callstack)) - be_raise(vm, "value_error", "invalid call depth level"); - if (getter(vm, level + 1, index)) { - be_return(vm); - } - be_return_nil(vm); -} - -static int m_varname(bvm *vm) -{ - return v_getname(vm, be_debug_varname); -} - -static int m_upvname(bvm *vm) -{ - return v_getname(vm, be_debug_upvname); -} -#endif - - -#if BE_USE_PERF_COUNTERS -static void map_insert(bvm *vm, const char *key, int value) -{ - be_pushstring(vm, key); - be_pushint(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); -} - -static int m_counters(bvm *vm) -{ - be_newobject(vm, "map"); - map_insert(vm, "instruction", vm->counter_ins); - map_insert(vm, "vmenter", vm->counter_enter); - map_insert(vm, "call", vm->counter_call); - map_insert(vm, "get", vm->counter_get); - map_insert(vm, "set", vm->counter_set); - map_insert(vm, "getgbl", vm->counter_get_global); - map_insert(vm, "try", vm->counter_try); - map_insert(vm, "raise", vm->counter_exc); - map_insert(vm, "objects", vm->counter_gc_kept); - map_insert(vm, "mem_alloc", vm->counter_mem_alloc); - map_insert(vm, "mem_free", vm->counter_mem_free); - map_insert(vm, "mem_realloc", vm->counter_mem_realloc); - be_pop(vm, 1); - be_return(vm); -} -#endif - -static int m_allocs(bvm *vm) { -#if BE_USE_PERF_COUNTERS - be_pushint(vm, vm->counter_mem_alloc); - be_return(vm); -#else - be_return_nil(vm); -#endif -} - -static int m_frees(bvm *vm) { -#if BE_USE_PERF_COUNTERS - be_pushint(vm, vm->counter_mem_free); - be_return(vm); -#else - be_return_nil(vm); -#endif -} - -static int m_reallocs(bvm *vm) { -#if BE_USE_PERF_COUNTERS - be_pushint(vm, vm->counter_mem_realloc); - be_return(vm); -#else - be_return_nil(vm); -#endif -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(debug) { - be_native_module_function("attrdump", m_attrdump), - be_native_module_function("codedump", m_codedump), - be_native_module_function("traceback", m_traceback), -#if BE_USE_DEBUG_HOOK - be_native_module_function("sethook", m_sethook), -#endif -#if BE_USE_PERF_COUNTERS - be_native_module_function("counters", m_counters), -#endif - be_native_module_function("calldepth", m_calldepth), - be_native_module_function("top", m_top), -#if BE_DEBUG_VAR_INFO - be_native_module_function("varname", m_varname), - be_native_module_function("upvname", m_upvname) -#endif - be_native_module_function("caller", m_caller), - be_native_module_function("gcdebug", m_gcdebug) -}; - -be_define_native_module(debug, NULL); -#else -/* @const_object_info_begin -module debug (scope: global, depend: BE_USE_DEBUG_MODULE) { - attrdump, func(m_attrdump) - codedump, func(m_codedump) - traceback, func(m_traceback) - sethook, func(m_sethook), BE_USE_DEBUG_HOOK - counters, func(m_counters), BE_USE_PERF_COUNTERS - calldepth, func(m_calldepth) - top, func(m_top) - varname, func(m_varname), BE_DEBUG_VAR_INFO - upvname, func(m_upvname), BE_DEBUG_VAR_INFO - caller, func(m_caller) - // individual counters - allocs, func(m_allocs) - frees, func(m_frees) - reallocs, func(m_reallocs) - // GC debug mode - gcdebug, func(m_gcdebug) -} -@const_object_info_end */ -#include "../generate/be_fixed_debug.h" -#endif - -#endif /* BE_USE_DEBUG_MODULE */ diff --git a/lib/libesp32/Berry/src/be_decoder.h b/lib/libesp32/Berry/src/be_decoder.h deleted file mode 100644 index c6cfd7ade636..000000000000 --- a/lib/libesp32/Berry/src/be_decoder.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_OPCODE_H -#define BE_OPCODE_H - -#define NO_JUMP -1 - -/* define field's bit-width */ -#define IOP_BITS 6u -#define IRA_BITS 8u -#define IRKB_BITS 9u -#define IRKC_BITS 9u - -/* define field's bit-width and positions */ -#define IRKC_POS 0u -#define IRKB_POS (IRKC_POS + IRKC_BITS) -#define IRA_POS (IRKB_POS + IRKB_BITS) -#define IOP_POS (IRA_POS + IRA_BITS) -#define IAx_BITS (IRA_BITS + IRKB_BITS + IRKC_BITS) -#define IBx_BITS (IRKC_BITS + IRKB_BITS) - -/* basic field operation */ -#define INS_MASK(pos, bits) ((binstruction)((1 << (bits)) - 1) << (pos)) -#define INS_GETx(i, mask, pos) cast_int(((binstruction)(i) & (mask)) >> (pos)) -#define INS_SETx(v, mask, pos) (((binstruction)(v) << (pos)) & (mask)) - -/* instruction operation */ -#define isK(v) (((v) & (1 << (IRKB_BITS - 1))) != 0) -#define setK(v) ((v) | (1 << (IRKB_BITS - 1))) -#define KR2idx(v) ((v) & 0xFF) -#define isKB(v) (((v) & (1 << (IRA_POS - 1))) != 0) -#define isKC(v) (((v) & (1 << (IRKB_POS - 1))) != 0) - -/* define masks and limit values */ -#define IOP_MASK INS_MASK(IOP_POS, IOP_BITS) -#define IRA_MASK INS_MASK(IRA_POS, IRA_BITS) -#define IRKB_MASK INS_MASK(IRKB_POS, IRKB_BITS) -#define IRKC_MASK INS_MASK(IRKC_POS, IRKC_BITS) -#define IAx_MASK INS_MASK(0, IAx_BITS) -#define IBx_MASK INS_MASK(0, IBx_BITS) -#define IsBx_MAX cast_int(IBx_MASK >> 1) -#define IsBx_MIN cast_int(-IsBx_MAX - 1) - -/* mask for K/R values */ -#define KR_MASK ((1 << (IRKB_BITS-1)) - 1) - -/* get field */ -#define IGET_OP(i) cast(bopcode, INS_GETx(i, IOP_MASK, IOP_POS)) -#define IGET_RA(i) INS_GETx(i, IRA_MASK, IRA_POS) -#define IGET_RKB(i) INS_GETx(i, IRKB_MASK, IRKB_POS) -#define IGET_RKC(i) INS_GETx(i, IRKC_MASK, IRKC_POS) -#define IGET_Bx(i) INS_GETx(i, IBx_MASK, 0) -#define IGET_sBx(i) (IGET_Bx(i) - IsBx_MAX) - -/* set field */ -#define ISET_OP(i) INS_SETx(i, IOP_MASK, IOP_POS) -#define ISET_RA(i) INS_SETx(i, IRA_MASK, IRA_POS) -#define ISET_RKB(i) INS_SETx(i, IRKB_MASK, IRKB_POS) -#define ISET_RKC(i) INS_SETx(i, IRKC_MASK, IRKC_POS) -#define ISET_Bx(i) INS_SETx(i, IBx_MASK, 0) -#define ISET_sBx(i) (ISET_Bx(cast_int(i) + IsBx_MAX)) - -typedef enum { - #define OPCODE(opc) OP_##opc - #include "be_opcodes.h" - #undef OPCODE -} bopcode; - -#endif diff --git a/lib/libesp32/Berry/src/be_exec.c b/lib/libesp32/Berry/src/be_exec.c deleted file mode 100644 index 794987933442..000000000000 --- a/lib/libesp32/Berry/src/be_exec.c +++ /dev/null @@ -1,522 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_exec.h" -#include "be_parser.h" -#include "be_vm.h" -#include "be_vector.h" -#include "be_mem.h" -#include "be_sys.h" -#include "be_debug.h" -#include "be_bytecode.h" -#include "be_decoder.h" -#include -#include - -#if !BE_USE_SCRIPT_COMPILER && !BE_USE_BYTECODE_LOADER - #error no compiler or bytecode loader enabled. -#endif - -#define FILE_BUFFER_SIZE 256 - -#define __STR(s) #s -#define STR(s) __STR(s) - -#define STACK_OVER_MSG(n) \ - "stack overflow (maximum stack size is " STR(n) ")" - -#ifdef BE_EXPLICIT_ABORT - #define _os_abort BE_EXPLICIT_ABORT -#else - #define _os_abort abort -#endif - -#ifdef BE_EXPLICIT_EXIT - #define _os_exit BE_EXPLICIT_EXIT -#else - #define _os_exit exit -#endif - -#define exec_try(j) if (be_setjmp((j)->b) == 0) -#define exec_throw(j) be_longjmp((j)->b, 1) - -#define fixup_ptr(ptr, offset) ((ptr) = (void*)((bbyte*)(ptr) + (offset))) -#define ptr_offset(ptr1, ptr2) ((bbyte*)(ptr1) - (bbyte*)(ptr2)) - -struct pparser { - const char *fname; - breader reader; - void *data; - bbyte islocal; -}; - -struct pcall { - bvalue *v; - int argc; -}; - -struct vmstate { - int top, reg, depth; - int refcount; -}; - -struct strbuf { - size_t len; - const char *s; -}; - -struct filebuf { - void *fp; - char buf[FILE_BUFFER_SIZE]; -}; - -void be_throw(bvm *vm, int errorcode) -{ -#if BE_USE_PERF_COUNTERS - vm->counter_exc++; -#endif - /* if BE_MALLOC_FAIL then call */ - if (errorcode == BE_MALLOC_FAIL) { - if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_MALLOC_FAIL, vm->gc.usage); - } - if (vm->errjmp) { - vm->errjmp->status = errorcode; - exec_throw(vm->errjmp); - } else { - _os_abort(); - } -} - -/* Fatal error Exit */ -/* Raise a BE_EXIT exception if within a try/catch block, or exit VM */ -BERRY_API void be_exit(bvm *vm, int status) -{ - if (vm->errjmp) { - be_pushint(vm, status); - be_pop(vm, 1); - be_throw(vm, BE_EXIT); - } else { - _os_exit(status); - } -} - -void be_throw_message(bvm *vm, int errorcode, const char *msg) -{ - be_pushstring(vm, msg); - be_throw(vm, errorcode); -} - -/* Exec protected: exec function and capture any exception and contain it within call */ -/* Exceptions or fatal errors are not propagated */ -int be_execprotected(bvm *vm, bpfunc f, void *data) -{ - struct blongjmp jmp; - jmp.status = 0; - jmp.prev = vm->errjmp; /* save long jump position */ - vm->errjmp = &jmp; - exec_try(vm->errjmp) { - f(vm, data); - } - vm->errjmp = jmp.prev; /* restore long jump position */ - return jmp.status; -} - -static void vm_state_save(bvm *vm, struct vmstate *state) -{ - state->depth = be_stack_count(&vm->callstack); - state->top = cast_int(vm->top - vm->stack); - state->reg = cast_int(vm->reg - vm->stack); - state->refcount = vm->refstack.count; -} - -static void copy_exception(bvm *vm, int res, int dstindex) -{ - bvalue *dst = vm->stack + dstindex; - if (res == BE_EXCEPTION || res == BE_EXIT) { - bvalue *src = vm->top; - *dst++ = *src++; - if (res == BE_EXCEPTION) { - *dst++ = *src++; - } - } - vm->top = dst; -} - -static void vm_state_restore(bvm *vm, const struct vmstate *state, int res) -{ - vm->reg = vm->stack + state->reg; - be_vector_resize(vm, &vm->refstack, state->refcount); - /* copy exception information to top */ - copy_exception(vm, res, state->top); - be_assert(be_stack_count(&vm->callstack) >= state->depth); - if (be_stack_count(&vm->callstack) > state->depth) { - be_vector_resize(vm, &vm->callstack, state->depth); - vm->cf = be_stack_top(&vm->callstack); - } -} - -#if BE_USE_SCRIPT_COMPILER -static void m_parser(bvm *vm, void *data) -{ - struct pparser *p = cast(struct pparser*, data); - bclosure *cl = be_parser_source(vm, - p->fname, p->reader, p->data, p->islocal); - var_setclosure(vm->top, cl); - be_incrtop(vm); -} - -int be_protectedparser(bvm *vm, - const char *fname, breader reader, void *data, bbool islocal) -{ - int res; - struct pparser s; - struct vmstate state; - s.fname = fname; - s.reader = reader; - s.data = data; - s.islocal = (bbyte)(islocal != 0); - vm_state_save(vm, &state); - res = be_execprotected(vm, m_parser, &s); - if (res) { /* restore call stack */ - vm_state_restore(vm, &state, res); - } - return res; -} - -static const char* _sgets(struct blexer* lexer, void *data, size_t *size) -{ - (void)lexer; - struct strbuf *sb = data; - *size = sb->len; - if (sb->len) { - sb->len = 0; - return sb->s; - } - return NULL; -} - -static const char* _fgets(struct blexer* lexer, void *data, size_t *size) -{ - (void)lexer; - struct filebuf *fb = data; - *size = be_fread(fb->fp, fb->buf, sizeof(fb->buf)); - if (*size) { - return fb->buf; - } - return NULL; -} - -BERRY_API int be_loadbuffer(bvm *vm, - const char *name, const char *buffer, size_t length) -{ - struct strbuf sbuf; - sbuf.s = buffer; - sbuf.len = length; - return be_protectedparser(vm, name, _sgets, &sbuf, bfalse); -} - -static int fileparser(bvm *vm, const char *name, bbool islocal) -{ - int res = BE_IO_ERROR; - struct filebuf *fbuf = be_malloc(vm, sizeof(struct filebuf)); - fbuf->fp = be_fopen(name, "r"); - if (fbuf->fp) { - res = be_protectedparser(vm, name, _fgets, fbuf, islocal); - be_fclose(fbuf->fp); - } - be_free(vm, fbuf, sizeof(struct filebuf)); - return res; -} -#endif /* BE_USE_SCRIPT_COMPILER */ - -#if BE_USE_BYTECODE_LOADER -static void bytecode_loader(bvm *vm, void *data) -{ - bclosure *cl = be_bytecode_load(vm, (const char *)data); - if (cl != NULL) { - var_setclosure(vm->top, cl); - } else { - var_setnil(vm->top); - } - be_incrtop(vm); -} - -/* load bytecode file */ -static int load_bytecode(bvm *vm, const char *name) -{ - int res = BE_SYNTAX_ERROR; - if (be_bytecode_check(name)) { - struct vmstate state; - vm_state_save(vm, &state); - res = be_execprotected(vm, bytecode_loader, (void*)name); - if (res) { /* restore call stack */ - vm_state_restore(vm, &state, res); - } - } - return res; -} - -#else -#define load_bytecode(vm, name) BE_SYNTAX_ERROR -#endif /* BE_USE_BYTECODE_LOADER */ - -BERRY_API int be_loadmode(bvm *vm, const char *name, bbool islocal) -{ - int res = load_bytecode(vm, name); -#if BE_USE_SCRIPT_COMPILER - if (res && res != BE_IO_ERROR && res != BE_EXCEPTION) { - res = fileparser(vm, name, islocal); - } -#else - (void)islocal; -#endif - if (res == BE_IO_ERROR) { - be_pushfstring(vm, "cannot open file '%s'.", name); - } - return res; -} - -#if BE_USE_BYTECODE_SAVER -static void _bytecode_save(bvm *vm, void *data) -{ - if (be_top(vm) > 0 && var_isclosure(vm->top - 1)) { - bclosure *cl = var_toobj(vm->top - 1); - be_bytecode_save(vm, (const char *)data, cl->proto); - } -} - -/* save bytecode file */ -BERRY_API int be_savecode(bvm *vm, const char *name) -{ - int res; - struct vmstate state; - vm_state_save(vm, &state); - res = be_execprotected(vm, _bytecode_save, (void *)name); - if (res) { /* restore call stack */ - vm_state_restore(vm, &state, res); - } - return res; -} -#endif - -static void m_pcall(bvm *vm, void *data) -{ - struct pcall *p = cast(struct pcall*, data); - be_dofunc(vm, p->v, p->argc); -} - -/* Protected call: contain any exception of fatal error and restore context if something went wrong */ -int be_protectedcall(bvm *vm, bvalue *v, int argc) -{ - int res; - struct pcall s; - struct vmstate state; - s.v = v; - s.argc = argc; - vm_state_save(vm, &state); - res = be_execprotected(vm, m_pcall, &s); - if (res) { /* restore call stack */ - vm_state_restore(vm, &state, res); - } - return res; -} - -#if BE_DEBUG && defined(be_assert) -/* increase top register and return new top */ -/* Does not expand the stack if there is not enough room, but may corrupt memory */ -bvalue* be_incrtop(bvm *vm) -{ - bvalue *top = vm->top++; - be_assert(top < vm->stacktop); - return top; -} -#endif - -/* TODO what is the difference with be_stack_push? */ -void be_stackpush(bvm *vm) -{ - /* make sure there is enough stack space */ - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - be_incrtop(vm); -} - -/* check that the stack is able to store `count` items, and increase stack if needed */ -BERRY_API void be_stack_require(bvm *vm, int count) -{ -#if BE_USE_DEBUG_STACK == 0 - if (vm->top + count >= vm->stacktop) { - be_stack_expansion(vm, count); - } -#else - be_stack_expansion(vm, vm->top - vm->stacktop + count); /* force exact resize each time */ -#endif -} - -/* Scan the entire callstack and adjust all pointer by `offset` */ -static void update_callstack(bvm *vm, intptr_t offset) -{ - bcallframe *cf = be_stack_top(&vm->callstack); - bcallframe *base = be_stack_base(&vm->callstack); - for (; cf >= base; --cf) { - fixup_ptr(cf->func, offset); - fixup_ptr(cf->top, offset); - fixup_ptr(cf->reg, offset); - } - fixup_ptr(vm->top, offset); - fixup_ptr(vm->reg, offset); -} - -static void update_upvalues(bvm *vm, intptr_t offset) -{ - bupval *node = vm->upvalist; - /* update the value referenced by open upvalues */ - for (; node != NULL; node = node->u.next) { - fixup_ptr(node->value, offset); - } -} - -/* Resize the stack to new `size` as number of elements */ -/* Then update all pointers in callstack and upvalues with the new stack address */ -static void stack_resize(bvm *vm, size_t size) -{ - intptr_t offset; - bvalue *old = vm->stack; /* save original pointer of stack before resize */ - size_t os = (vm->stacktop - old) * sizeof(bvalue); /* size of current stack allocated in bytes */ -#if BE_USE_DEBUG_STACK == 0 - vm->stack = be_realloc(vm, old, os, sizeof(bvalue) * size); /* reallocate with the new size */ -#else /* force a reallocation */ - size_t ns = sizeof(bvalue) * size; - vm->stack = be_malloc(vm, ns); - size_t transf = (os < ns) ? os : ns; /* min size */ - memmove(vm->stack, old, transf); /* copy to new location */ - memset(old, 0xFF, os); /* fill the structure with invalid pointers */ - be_free(vm, old, os); -#endif - vm->stacktop = vm->stack + size; /* compute new stacktop */ - offset = ptr_offset(vm->stack, old); /* compute the address difference between old and ne stack addresses */ - /* update callframes */ - update_callstack(vm, offset); - /* update open upvalues */ - update_upvalues(vm, offset); -} - -/* Stack resize internal API */ -/* Increases the stack by `n` elements, reallocate stack if needed and update all callstacks and upvals */ -/* Check if we are above the max allowed stack */ -void be_stack_expansion(bvm *vm, int n) -{ - int size = vm->stacktop - vm->stack; /* with debug enabled, stack increase may be negative */ - /* check new stack size */ - if (size + n > BE_STACK_TOTAL_MAX) { - /* ensure the stack is enough when generating error messages. */ - stack_resize(vm, size + 1); - be_raise(vm, "runtime_error", STACK_OVER_MSG(BE_STACK_TOTAL_MAX)); - } - if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_STACK_RESIZE_START, size * sizeof(bvalue), (size + n) * sizeof(bvalue)); - stack_resize(vm, size + n); -} - -static void fixup_exceptstack(bvm* vm, struct bexecptframe* lbase) -{ - struct bexecptframe *base = be_stack_base(&vm->exceptstack); - if (lbase != base) { /* the address has changed when the stack is expanded */ - struct bexecptframe *top = be_stack_top(&vm->exceptstack); - bbyte *begin = (bbyte*)&lbase->errjmp; - bbyte *end = (bbyte*)&(lbase + (top - base))->errjmp; - intptr_t offset = ptr_offset(base, lbase); - struct blongjmp *errjmp = vm->errjmp; - while (errjmp) { - bbyte *prev = (bbyte*)errjmp->prev; - if (prev >= begin && prev < end) { - fixup_ptr(prev, offset); /* fixup the prev pointer */ - errjmp->prev = (struct blongjmp*)prev; - } - errjmp = (struct blongjmp*)prev; - } - } -} - -/* set an exception handling recovery point. To do this, we have to - * push some VM states into the exception stack. */ -void be_except_block_setup(bvm *vm) -{ - struct bexecptframe *frame; - struct bexecptframe *lbase = be_stack_base(&vm->exceptstack); - be_stack_push(vm, &vm->exceptstack, NULL); - frame = be_stack_top(&vm->exceptstack); - frame->depth = be_stack_count(&vm->callstack); /* the call stack depth */ - frame->ip = vm->ip; /* OP_EXBLK's next instruction pointer */ - /* set longjmp() jump point */ - frame->errjmp.status = 0; - frame->errjmp.prev = vm->errjmp; /* save long jump list */ - frame->refcount = vm->refstack.count; /* save reference pointer */ - vm->errjmp = &frame->errjmp; - fixup_exceptstack(vm, lbase); -} - -/* resumes to the state of the previous frame when an exception occurs. */ -void be_except_block_resume(bvm *vm) -{ - int errorcode = vm->errjmp->status; - struct bexecptframe *frame = be_stack_top(&vm->exceptstack); - if (errorcode == BE_EXCEPTION) { - vm->errjmp = vm->errjmp->prev; - be_vector_resize(vm, &vm->refstack, frame->refcount); - /* jump to except instruction */ - vm->ip = frame->ip + IGET_sBx(frame->ip[-1]); - if (be_stack_count(&vm->callstack) > frame->depth) { - bvalue *top = vm->top; - bcallframe *cf = be_vector_at(&vm->callstack, frame->depth); - vm->top = cf->top; - vm->reg = cf->reg; - vm->cf = frame->depth ? cf - 1 : NULL; - be_vector_resize(vm, &vm->callstack, frame->depth); - /* copy the exception value and argument to the top of - * the current function */ - vm->top[0] = top[0]; /* exception value */ - vm->top[1] = top[1]; /* exception argument */ - } - be_stack_pop(&vm->exceptstack); - } else { /* other errors cannot be catch by the except block */ - /* find the next error handling location */ - while (vm->errjmp == &frame->errjmp) { - vm->errjmp = vm->errjmp->prev; - be_stack_pop(&vm->exceptstack); - frame = be_stack_top(&vm->exceptstack); - } - be_throw(vm, errorcode); /* rethrow this exception */ - } -} - -/* only close the except block, no other operations */ -void be_except_block_close(bvm *vm, int count) -{ - struct bexecptframe *frame; - int size = be_stack_count(&vm->exceptstack); - be_assert(count > 0 && count <= size); - frame = be_vector_at(&vm->exceptstack, size - count); - vm->errjmp = frame->errjmp.prev; - be_vector_resize(vm, &vm->exceptstack, size - count); -} - -void be_save_stacktrace(bvm *vm) -{ - bstack *stack = &vm->tracestack; - be_stack_clear(stack); - if (be_stack_count(&vm->callstack)) { - bcallframe *cf; - bcallframe *base = be_stack_base(&vm->callstack); - bcallframe *top = be_stack_top(&vm->callstack); - for (cf = base; cf <= top; ++cf) { - bcallsnapshot *st; - be_stack_push(vm, stack, NULL); - st = be_stack_top(stack); - st->func = *cf->func; - st->ip = cf == top ? vm->ip : cf[1].ip; - } - } -} diff --git a/lib/libesp32/Berry/src/be_exec.h b/lib/libesp32/Berry/src/be_exec.h deleted file mode 100644 index af10bf255f67..000000000000 --- a/lib/libesp32/Berry/src/be_exec.h +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_EXEC_H -#define BE_EXEC_H - -#include "be_object.h" -#include - -/* protected-call function */ -typedef void (*bpfunc)(bvm *vm, void *data); - -#if BE_DEBUG -bvalue* be_incrtop(bvm *vm); -#else -/* increase top register */ -#define be_incrtop(vm) ((vm)->top++) -#endif - -#define be_stackpop(vm, n) ((vm)->top -= (n)) - -/* in MinGW-w64, setjmp / longjmp may be broken, - * so here is replaced by __builtin version. */ -#if defined(__GNUC__) && defined(__MINGW32__) - #define be_setjmp(env) __builtin_setjmp(env) - #define be_longjmp(env, v) __builtin_longjmp(env, v) -#else - #define be_setjmp(env) setjmp(env) - #define be_longjmp(env, v) longjmp(env, v) -#endif - -typedef jmp_buf bjmpbuf; - -struct blongjmp { - bjmpbuf b; - struct blongjmp *prev; - volatile int status; /* error code */ -}; - -struct bexecptframe { - struct blongjmp errjmp; /* long jump information */ - int depth; /* function call stack depth */ - binstruction *ip; /* instruction pointer */ - int refcount; /* save object reference stack */ -}; - -void be_throw(bvm *vm, int errorcode); -int be_execprotected(bvm *vm, bpfunc f, void *data); -int be_protectedparser(bvm *vm, const char *fname, - breader reader, void *data, bbool islocal); -int be_protectedcall(bvm *vm, bvalue *v, int argc); -void be_stackpush(bvm *vm); -void be_stack_expansion(bvm *vm, int n); -void be_except_block_setup(bvm *vm); -void be_except_block_resume(bvm *vm); -void be_except_block_close(bvm *vm, int count); -void be_save_stacktrace(bvm *vm); - -#endif diff --git a/lib/libesp32/Berry/src/be_filelib.c b/lib/libesp32/Berry/src/be_filelib.c deleted file mode 100644 index dcf661fded1e..000000000000 --- a/lib/libesp32/Berry/src/be_filelib.c +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_mem.h" -#include "be_sys.h" -#include "be_gc.h" -#include "be_bytecode.h" -#include "be_vm.h" -#include - -#define READLINE_STEP 100 - -static int i_write(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - if(be_iscomptr(vm, -1) && (be_isstring(vm, 2) || be_isbytes(vm, 2))) { - void *fh = be_tocomptr(vm, -1); - size_t size = 0; - const char *data = NULL; - if (be_isstring(vm, 2)) { - data = be_tostring(vm, 2); - size = be_strlen(vm, 2); - } else { - data = be_tobytes(vm, 2, &size); - } - size_t bw = be_fwrite(fh, data, size); - if (bw != size) { - be_raise(vm, "io_error", "write failed"); - } - } - be_return_nil(vm); -} - -static size_t readsize(bvm *vm, int argc, void *fh) -{ - if (argc >=2 && be_isint(vm, 2)) { - return be_toindex(vm, 2); - } - return be_fsize(fh) - be_ftell(fh); -} - -static int i_read(bvm *vm) -{ - int argc = be_top(vm); - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - size_t size = readsize(vm, argc, fh); - if (size) { - char *buffer = be_malloc(vm, size); - size = be_fread(fh, buffer, size); - be_pushnstring(vm, buffer, size); - be_free(vm, buffer, size); - } else { - be_pushstring(vm, ""); - } - be_return(vm); - } - be_return_nil(vm); -} - -static int i_readbytes(bvm *vm) -{ - int argc = be_top(vm); - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - size_t size = readsize(vm, argc, fh); - if (size) { - if (size > vm->bytesmaxsize) { - be_raise(vm, "memory_error", "size exceeds maximum allowed for bytes"); - } - /* avoid double allocation, using directly the internal buffer of bytes() */ - be_getbuiltin(vm, "bytes"); - be_pushint(vm, size); - be_call(vm, 1); /* call bytes() constructor with pre-sized buffer */ - be_pop(vm, 1); /* bytes() instance is at top */ - - /* read back the actual buffer size */ - be_getmember(vm, -1, ".size"); - int32_t bytes_size = be_toint(vm, -1); - be_pop(vm, 1); - if (bytes_size < (int32_t)size) { - be_raise(vm, "memory_error", "could not allocated buffer"); - } - - be_getmember(vm, -1, "resize"); - be_pushvalue(vm, -2); - be_pushint(vm, size); - be_call(vm, 2); /* call b.resize(size) */ - be_pop(vm, 3); /* bytes() instance is at top */ - - char *buffer = (char*) be_tobytes(vm, -1, NULL); /* we get the address of the internal buffer of size 'size' */ - size_t read_size = be_fread(fh, buffer, size); - - if (size != read_size) { - /* resize if something went wrong */ - be_getmember(vm, -1, "resize"); - be_pushvalue(vm, -2); - be_pushint(vm, read_size); - be_call(vm, 2); /* call b.resize(size) */ - be_pop(vm, 3); /* bytes() instance is at top */ - } - } else { - be_pushbytes(vm, NULL, 0); - } - be_return(vm); - } - be_return_nil(vm); -} - -static int i_readline(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - size_t pos = 0, size = READLINE_STEP; - char *buffer = be_malloc(vm, size); - char *res = be_fgets(fh, buffer, (int)size); - while (res) { - pos += strlen(buffer + pos); - if (!pos || buffer[pos - 1] == '\n') { - break; - } - buffer = be_realloc(vm, buffer, size, size + READLINE_STEP); - res = be_fgets(fh, buffer + pos, READLINE_STEP); - size += READLINE_STEP; - } - be_pushnstring(vm, buffer, pos); - be_free(vm, buffer, size); - be_return(vm); - } - be_return_nil(vm); -} - -static int i_seek(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1) && be_isint(vm, 2)) { - void *fh = be_tocomptr(vm, -1); - be_fseek(fh, be_toindex(vm, 2)); - } - be_return_nil(vm); -} - -static int i_tell(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - size_t pos = be_ftell(fh); - be_pushint(vm, cast(bint, pos)); - be_return(vm); - } - be_return_nil(vm); -} - -static int i_size(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - size_t pos = be_fsize(fh); - be_pushint(vm, cast(bint, pos)); - be_return(vm); - } - be_return_nil(vm); -} - -static int i_flush(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - be_fflush(fh); - } - be_return_nil(vm); -} - -static int i_close(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - be_fclose(fh); - be_pushnil(vm); - be_setmember(vm, 1, ".p"); - } - be_return_nil(vm); -} - -static int i_savecode(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 2 && be_isclosure(vm, 2)) { - be_getmember(vm, 1, ".p"); - if (be_iscomptr(vm, -1)) { - void *fh = be_tocomptr(vm, -1); - bvalue *v = be_indexof(vm, 2); - if (var_isclosure(v)) { - bclosure *cl = var_toobj(v); - bproto *pr = cl->proto; - be_bytecode_save_to_fs(vm, fh, pr); - } - } - } else { - be_raise(vm, "type_error", "closure expected"); - } - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -static int m_open(bvm *vm) -#else -int be_nfunc_open(bvm *vm) -#endif -{ - int argc = be_top(vm); - const char *fname, *mode; - static const bnfuncinfo members[] = { - { ".p", NULL }, - { "write", i_write }, - { "read", i_read }, - { "readbytes", i_readbytes }, - { "readline", i_readline }, - { "seek", i_seek }, - { "tell", i_tell }, - { "size", i_size }, - { "flush", i_flush }, - { "close", i_close }, - { "deinit", i_close }, - { "savecode", i_savecode }, - { NULL, NULL } - }; - fname = argc >= 1 && be_isstring(vm, 1) ? be_tostring(vm, 1) : NULL; - mode = argc >= 2 && be_isstring(vm, 2) ? be_tostring(vm, 2) : "r"; - if (fname) { - void *fh = be_fopen(fname, mode); - if (fh == NULL) { - be_raise(vm, "io_error", - be_pushfstring(vm, "cannot open file '%s'", fname)); - } - be_pushclass(vm, "file", members); - be_call(vm, 0); - be_pushcomptr(vm, fh); - be_setmember(vm, -2, ".p"); - be_pop(vm, 1); - be_return(vm); - } - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -void be_load_filelib(bvm *vm) -{ - be_regfunc(vm, "open", m_open); -} -#endif diff --git a/lib/libesp32/Berry/src/be_func.c b/lib/libesp32/Berry/src/be_func.c deleted file mode 100644 index b1280d9ec0ae..000000000000 --- a/lib/libesp32/Berry/src/be_func.c +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_func.h" -#include "be_gc.h" -#include "be_mem.h" -#include "be_vm.h" -#include "be_exec.h" -#include - -#define clousersize(n) \ - (sizeof(bclosure) + sizeof(bupval*) * ((size_t)(n) - 1)) - -static bupval* findupval(bvm *vm, bvalue *level) -{ - bupval *node = vm->upvalist; - while (node != NULL && node->value > level) { - node = node->u.next; - } - if (!node || node->value != level) { - /* not found */ - node = be_malloc(vm, sizeof(bupval)); - node->value = level; - node->refcnt = 0; - /* insert to list head */ - node->u.next = vm->upvalist; - vm->upvalist = node; - } - return node; -} - -void be_initupvals(bvm *vm, bclosure *cl) -{ - int count = cl->proto->nupvals; - bupvaldesc *desc = cl->proto->upvals; - bvalue *stack = vm->reg; - bupval **uv = cl->upvals; - bupval **superuv = cast(bclosure*, var_toobj(vm->cf->func))->upvals; - for (; count--; desc++, uv++) { - if (desc->instack) { - bvalue *ref = stack + desc->idx; - *uv = findupval(vm, ref); - } else { - *uv = superuv[desc->idx]; - } - (*uv)->refcnt++; - } -} - -void be_upvals_close(bvm *vm, bvalue *level) -{ - bupval *node = vm->upvalist, *next; - bupval **prev = &vm->upvalist; - while (node) { - next = node->u.next; - if (node->value >= level) { - if (!node->refcnt) { - be_free(vm, node, sizeof(bupval)); - } else { - node->u.value = *node->value; /* move value to upvalue slot */ - node->value = &node->u.value; - } - *prev = next; /* remove from linked list */ - } else { - prev = &node->u.next; - } - node = next; - } -} - -void be_release_upvalues(bvm *vm, bclosure *cl) -{ - int i, count = cl->nupvals; - for (i = 0; i < count; ++i) { - bupval *uv = cl->upvals[i]; - if (uv) { - if (uv->refcnt) { - --uv->refcnt; - } - /* delete non-referenced closed upvalue */ - if (uv->value == &uv->u.value && !uv->refcnt) { - be_free(vm, uv, sizeof(bupval)); - } - } - } -} - -bproto* be_newproto(bvm *vm) -{ - bgcobject *gco = be_gcnew(vm, BE_PROTO, bproto); - bproto *p = cast_proto(gco); - if (p) { - p->upvals = NULL; - p->ktab = NULL; - p->ptab = NULL; - p->code = NULL; - p->name = NULL; - p->gray = NULL; - p->codesize = 0; - p->nupvals = 0; - p->nproto = 0; - p->nconst = 0; - p->nstack = 0; - p->codesize = 0; - p->argc = 0; - p->varg = 0; -#if BE_DEBUG_SOURCE_FILE - p->source = NULL; -#endif -#if BE_DEBUG_RUNTIME_INFO - p->lineinfo = NULL; - p->nlineinfo = 0; -#endif -#if BE_DEBUG_VAR_INFO - p->varinfo = NULL; - p->nvarinfo = 0; -#endif - } - return p; -} - -bclosure* be_newclosure(bvm *vm, int nupval) -{ - bgcobject *gco = be_newgcobj(vm, BE_CLOSURE, clousersize(nupval)); - bclosure *cl = cast_closure(gco); - if (cl) { - cl->proto = NULL; - cl->nupvals = (bbyte)nupval; - while (nupval--) { - cl->upvals[nupval] = NULL; - } - } - return cl; -} - -static void init_upvals(bvm *vm, bntvclos *f) -{ - int count = f->nupvals; - bupval **upvals = &be_ntvclos_upval(f, 0); - while (count--) { - bupval *uv = be_malloc(vm, sizeof(bupval)); /* was closed */ - uv->value = &uv->u.value; - uv->refcnt = 1; - var_setnil(uv->value); - *upvals++ = uv; - } -} - -bntvclos* be_newntvclosure(bvm *vm, bntvfunc cf, int nupvals) -{ - size_t size = sizeof(bntvclos) + sizeof(bupval*) * nupvals; - bgcobject *gco = be_newgcobj(vm, BE_NTVCLOS, size); - bntvclos *f = cast_ntvclos(gco); - if (f) { - f->f = cf; - f->nupvals = (bbyte)nupvals; - if (nupvals) { - var_setntvclos(vm->top, f); - be_incrtop(vm); - init_upvals(vm, f); /* may be GC */ - be_stackpop(vm, 1); - } - } - return f; -} - -#if BE_DEBUG_VAR_INFO -bstring* be_func_varname(bproto *proto, int index, int pc) -{ - int i, nvarinfo = proto->nvarinfo; - bvarinfo *varinfo = proto->varinfo; - for (i = 0; i < nvarinfo && varinfo[i].beginpc <= pc; ++i) { - if (pc <= varinfo[i].endpc && index-- == 0) { - return varinfo[i].name; - } - } - return NULL; -} -#endif diff --git a/lib/libesp32/Berry/src/be_func.h b/lib/libesp32/Berry/src/be_func.h deleted file mode 100644 index a9cdaa127213..000000000000 --- a/lib/libesp32/Berry/src/be_func.h +++ /dev/null @@ -1,27 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_FUNC_H -#define BE_FUNC_H - -#include "be_object.h" - -#define be_newntvclos(vm, cf) \ - be_newntvclosure(vm, cf, 0) - -#define be_ntvclos_upval(cc, n) \ - (((bupval**)((size_t)cc + sizeof(bntvclos)))[n]) - -void be_initupvals(bvm *vm, bclosure *cl); -void be_upvals_close(bvm *vm, bvalue *level); -void be_release_upvalues(bvm *vm, bclosure *cl); -bproto* be_newproto(bvm *vm); -bclosure* be_newclosure(bvm *vm, int nupval); -bntvclos* be_newntvclosure(bvm *vm, bntvfunc cf, int nupvals); -bstring* be_func_varname(bproto *proto, int index, int pc); - -#endif diff --git a/lib/libesp32/Berry/src/be_gc.c b/lib/libesp32/Berry/src/be_gc.c deleted file mode 100644 index 35b0737f77bc..000000000000 --- a/lib/libesp32/Berry/src/be_gc.c +++ /dev/null @@ -1,613 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_gc.h" -#include "be_vm.h" -#include "be_mem.h" -#include "be_var.h" -#include "be_vector.h" -#include "be_string.h" -#include "be_class.h" -#include "be_list.h" -#include "be_func.h" -#include "be_map.h" -#include "be_module.h" -#include "be_exec.h" -#include "be_debug.h" - -#define GC_PAUSE (1 << 0) /* GC will not be executed automatically */ -#define GC_HALT (1 << 1) /* GC completely stopped */ -#define GC_ALLOC (1 << 2) /* GC in alloc */ - -#define gc_try(expr) be_assert(expr); if (expr) -#define gc_setdark_safe(o) if (o) gc_setdark(o) - -#define next_threshold(gc) ((gc).usage * ((size_t)(gc).steprate + 100) / 100) - -#define link_gray(vm, obj) { \ - (obj)->gray = (vm)->gc.gray; \ - (vm)->gc.gray = gc_object(obj); \ -} - -static void destruct_object(bvm *vm, bgcobject *obj); -static void free_object(bvm *vm, bgcobject *obj); - -void be_gc_init(bvm *vm) -{ - vm->gc.usage = sizeof(bvm); - be_gc_setsteprate(vm, 200); - be_gc_init_memory_pools(vm); -} - -void be_gc_deleteall(bvm *vm) -{ - bupval *uv, *uvnext; - bgcobject *node, *next; - /* halt GC and delete all objects */ - vm->gc.status |= GC_HALT; - /* first: call destructor */ - for (node = vm->gc.list; node; node = node->next) { - destruct_object(vm, node); - } - /* second: free objects */ - for (node = vm->gc.list; node; node = next) { - next = node->next; - free_object(vm, node); - } - /* delete open upvalue list */ - for (uv = vm->upvalist; uv; uv = uvnext) { - uvnext = uv->u.next; - be_free(vm, uv, sizeof(bupval)); - } -} - -void be_gc_setsteprate(bvm *vm, int rate) -{ - be_assert(rate >= 100 && rate <= 355); - vm->gc.steprate = (bbyte)(rate - 100); - vm->gc.threshold = next_threshold(vm->gc); -} - -void be_gc_setpause(bvm *vm, int pause) -{ - if (pause) { - vm->gc.status |= GC_PAUSE; - } else { - vm->gc.status &= ~GC_PAUSE; - } -} - -bgcobject* be_newgcobj(bvm *vm, int type, size_t size) -{ - bgcobject *obj = be_malloc(vm, size); - be_gc_auto(vm); - var_settype(obj, (bbyte)type); /* mark the object type */ - obj->marked = GC_WHITE; /* default gc object type is white */ - obj->next = vm->gc.list; /* link to the next field */ - vm->gc.list = obj; /* insert to head */ - return obj; -} - -bgcobject* be_gc_newstr(bvm *vm, size_t size, int islong) -{ - bgcobject *obj; - if (islong) { /* creating long strings is similar to ordinary GC objects */ - return be_newgcobj(vm, BE_STRING, size); - } - obj = be_malloc(vm, size); - be_gc_auto(vm); - var_settype(obj, BE_STRING); /* mark the object type to BE_STRING */ - obj->marked = GC_WHITE; /* default string type is white */ - return obj; -} - -void be_gc_fix(bvm *vm, bgcobject *obj) -{ - (void)vm; - if (!gc_isconst(obj)) { - gc_setfixed(obj); - } -} - -void be_gc_unfix(bvm *vm, bgcobject *obj) -{ - (void)vm; - if (!gc_isconst(obj)) { - gc_clearfixed(obj); - } -} - -bbool be_gc_fix_set(bvm *vm, bgcobject *obj, bbool fix) -{ - (void)vm; - bbool was_fixed = gc_isfixed(obj); - if (!gc_isconst(obj)) { - if (fix) { - gc_setfixed(obj); - } else { - gc_clearfixed(obj); - } - } - return was_fixed; -} - - -#if BE_USE_PERF_COUNTERS -#define GC_MARK(type) do { vm->gc_mark_##type++; } while (0); -#else -#define GC_MARK(type) do { } while (0); -#endif - -static void mark_gray_reset_counters(bvm *vm) { -#if BE_USE_PERF_COUNTERS - vm->gc_mark_string = 0; - vm->gc_mark_class = 0; - vm->gc_mark_proto = 0; - vm->gc_mark_instance = 0; - vm->gc_mark_map = 0; - vm->gc_mark_list = 0; - vm->gc_mark_closure = 0; - vm->gc_mark_ntvclos = 0; - vm->gc_mark_module = 0; - vm->gc_mark_comobj = 0; -#endif -} - -static void mark_gray(bvm *vm, bgcobject *obj) -{ - if (obj && gc_iswhite(obj) && !gc_isconst(obj)) { - gc_setgray(obj); - be_assert(!var_isstatic(obj)); - switch (var_primetype(obj)) { - case BE_STRING: gc_setdark(obj); GC_MARK(string); break; /* just set dark */ - case BE_CLASS: link_gray(vm, cast_class(obj)); GC_MARK(class); break; - case BE_PROTO: link_gray(vm, cast_proto(obj)); GC_MARK(proto); break; - case BE_INSTANCE: link_gray(vm, cast_instance(obj)); GC_MARK(instance); break; - case BE_MAP: link_gray(vm, cast_map(obj)); GC_MARK(map); break; - case BE_LIST: link_gray(vm, cast_list(obj)); GC_MARK(list); break; - case BE_CLOSURE: link_gray(vm, cast_closure(obj)); GC_MARK(closure); break; - case BE_NTVCLOS: link_gray(vm, cast_ntvclos(obj)); GC_MARK(ntvclos); break; - case BE_MODULE: link_gray(vm, cast_module(obj)); GC_MARK(module); break; - case BE_COMOBJ: gc_setdark(obj); GC_MARK(comobj); break; /* just set dark */ - default: break; - } - } -} - -static void mark_gray_var(bvm *vm, bvalue *value) -{ - if (be_isgcobj(value)) { - mark_gray(vm, var_togc(value)); - } -} - -static void mark_map(bvm *vm, bgcobject *obj) -{ - bmap *map = cast_map(obj); - gc_try (map != NULL) { - bmapnode *node; - bmapiter iter = be_map_iter(); - vm->gc.gray = map->gray; /* remove object from gray list */ - while ((node = be_map_next(map, &iter)) != NULL) { - bmapkey *key = &node->key; - bvalue *val = &node->value; - if (be_isgcobj(key)) { - mark_gray(vm, var_togc(key)); - } - mark_gray_var(vm, val); - } - } -} - -static void mark_list(bvm *vm, bgcobject *obj) -{ - blist *list = cast_list(obj); - gc_try (list != NULL) { - bvalue *val = be_list_data(list); - bvalue *end = be_list_end(list); - vm->gc.gray = list->gray; /* remove object from gray list */ - for (; val < end; val++) { - mark_gray_var(vm, val); - } - } -} - -static void mark_proto(bvm *vm, bgcobject *obj) -{ - bproto *p = cast_proto(obj); - gc_try (p != NULL) { - int count; - bvalue *k = p->ktab; - bproto **ptab = p->ptab; - vm->gc.gray = p->gray; /* remove object from gray list */ - for (count = p->nconst; count--; ++k) { - mark_gray_var(vm, k); - } - for (count = p->nproto; count--; ++ptab) { - mark_gray(vm, gc_object(*ptab)); - } - gc_setdark_safe(p->name); -#if BE_DEBUG_SOURCE_FILE - gc_setdark_safe(p->source); -#endif -#if BE_DEBUG_VAR_INFO - if (p->nvarinfo) { - bvarinfo *vinfo = p->varinfo; - be_assert(vinfo != NULL); - for (count = p->nvarinfo; count--; ++vinfo) { - gc_setdark_safe(vinfo->name); - } - } -#endif - } -} - -static void mark_closure(bvm *vm, bgcobject *obj) -{ - bclosure *cl = cast_closure(obj); - gc_try (cl != NULL) { - int count = cl->nupvals; - bupval **uv = cl->upvals; - vm->gc.gray = cl->gray; /* remove object from gray list */ - for (; count--; ++uv) { - if (*uv && (*uv)->refcnt) { - mark_gray_var(vm, (*uv)->value); - } - } - mark_gray(vm, gc_object(cl->proto)); - } -} - -static void mark_ntvclos(bvm *vm, bgcobject *obj) -{ - bntvclos *f = cast_ntvclos(obj); - gc_try (f != NULL) { - int count = f->nupvals; - bupval **uv = &be_ntvclos_upval(f, 0); - vm->gc.gray = f->gray; /* remove object from gray list */ - for (; count--; ++uv) { - if (*uv && (*uv)->refcnt) { - mark_gray_var(vm, (*uv)->value); - } - } - } -} - -static void mark_class(bvm *vm, bgcobject *obj) -{ - bclass *c = cast_class(obj); - gc_try (c != NULL) { - vm->gc.gray = c->gray; /* remove object from gray list */ - mark_gray(vm, gc_object(be_class_name(c))); - mark_gray(vm, gc_object(be_class_members(c))); - mark_gray(vm, gc_object(be_class_super(c))); - } -} - -static void mark_instance(bvm *vm, bgcobject *obj) -{ - binstance *o = cast_instance(obj); - gc_try (o != NULL) { - bvalue *var = be_instance_members(o); - int nvar = be_instance_member_count(o); - vm->gc.gray = o->gray; /* remove object from gray list */ - mark_gray(vm, gc_object(be_instance_class(o))); - mark_gray(vm, gc_object(be_instance_super(o))); - for (; nvar--; var++) { /* mark variables */ - mark_gray_var(vm, var); - } - } -} - -static void mark_module(bvm *vm, bgcobject *obj) -{ - bmodule *o = cast_module(obj); - gc_try (o != NULL) { - vm->gc.gray = o->gray; /* remove object from gray list */ - mark_gray(vm, gc_object(o->table)); - if (!gc_isconst(o) && gc_exmark(o) & BE_MODULE_NAME) { - mark_gray(vm, gc_object(o->info.sname)); - } - } -} - -static void free_proto(bvm *vm, bgcobject *obj) -{ - bproto *proto = cast_proto(obj); - gc_try (proto != NULL) { - be_free(vm, proto->upvals, proto->nupvals * sizeof(bupvaldesc)); - if (!(proto->varg & BE_VA_SHARED_KTAB)) { /* do not free shared ktab */ - /*caveat: the shared ktab is never GCed, in practice this is not a problem */ - /* since shared ktab are primarily meant for solidification hence not gc-able */ - be_free(vm, proto->ktab, proto->nconst * sizeof(bvalue)); - } - be_free(vm, proto->ptab, proto->nproto * sizeof(bproto*)); - be_free(vm, proto->code, proto->codesize * sizeof(binstruction)); -#if BE_DEBUG_RUNTIME_INFO - be_free(vm, proto->lineinfo, proto->nlineinfo * sizeof(blineinfo)); -#endif -#if BE_DEBUG_VAR_INFO - be_free(vm, proto->varinfo, proto->nvarinfo * sizeof(bvarinfo)); -#endif - be_free(vm, proto, sizeof(bproto)); - } -} - -static void free_closure(bvm *vm, bgcobject *obj) -{ - bclosure *cl = cast_closure(obj); - gc_try (cl != NULL) { - int count = cl->nupvals; - be_release_upvalues(vm, cl); - be_free(vm, cl, sizeof(bclosure) - + sizeof(bupval*) * ((size_t)count - 1)); - } -} - -static void free_ntvclos(bvm *vm, bgcobject *obj) -{ - bntvclos *f = cast_ntvclos(obj); - gc_try (f != NULL) { - int count = f->nupvals; - bupval **uv = &be_ntvclos_upval(f, 0); - while (count--) { - be_free(vm, *uv++, sizeof(bupval)); - } - be_free(vm, f, sizeof(bntvclos) + sizeof(bupval*) * f->nupvals); - } -} - -static void free_lstring(bvm *vm, bgcobject *obj) -{ - blstring *ls = gc_cast(obj, BE_STRING, blstring); - gc_try (ls != NULL) { - be_free(vm, ls, sizeof(blstring) + ls->llen + 1); - } -} - -static void free_instance(bvm *vm, bgcobject *obj) -{ - binstance *o = cast_instance(obj); - int nvar = be_instance_member_count(o); - be_free(vm, obj, sizeof(binstance) + sizeof(bvalue) * (nvar - 1)); -} - -static void free_object(bvm *vm, bgcobject *obj) -{ - switch (var_primetype(obj)) { - case BE_STRING: free_lstring(vm, obj); break; /* long string */ - case BE_CLASS: be_free(vm, obj, sizeof(bclass)); break; - case BE_INSTANCE: free_instance(vm, obj); break; - case BE_MAP: be_map_delete(vm, cast_map(obj)); break; - case BE_LIST: be_list_delete(vm, cast_list(obj)); break; - case BE_CLOSURE: free_closure(vm, obj); break; - case BE_NTVCLOS: free_ntvclos(vm, obj); break; - case BE_PROTO: free_proto(vm, obj); break; - case BE_MODULE: be_module_delete(vm, cast_module(obj)); break; - case BE_COMOBJ: be_commonobj_delete(vm, obj); break; - default: break; /* case BE_STRING: break; */ - } -} - -static void premark_internal(bvm *vm) -{ - mark_gray(vm, gc_object(vm->module.loaded)); - mark_gray(vm, gc_object(vm->module.path)); - mark_gray(vm, gc_object(vm->ntvclass)); -#if BE_USE_DEBUG_HOOK - if (be_isgcobj(&vm->hook)) { - mark_gray(vm, gc_object(var_toobj(&vm->hook))); - } -#endif -} - -static void premark_global(bvm *vm) -{ - bvalue *v = vm->gbldesc.global.vlist.data; - bvalue *end = v + be_global_count(vm); - while (v < end) { - if (be_isgcobj(v)) { - mark_gray(vm, var_togc(v)); - } - ++v; - } - v = vm->gbldesc.builtin.vlist.data; - end = v + be_builtin_count(vm); - while (v < end) { - mark_gray_var(vm, v++); - } -} - -static void premark_stack(bvm *vm) -{ - bvalue *v = vm->stack, *end = vm->top; - /* mark live objects */ - for (; v < end; ++v) { - mark_gray_var(vm, v); - } - /* set other values to nil */ - end = vm->stacktop; - for (; v < end; ++v) { - var_setnil(v); - } -} - -static void premark_tracestack(bvm *vm) -{ - bcallsnapshot *cf = be_vector_data(&vm->tracestack); - bcallsnapshot *end = be_vector_end(&vm->tracestack); - for (; cf <= end; ++cf) { - mark_gray_var(vm, &cf->func); - } -} - -static void premark_fixed(bvm *vm) -{ - bgcobject *node = vm->gc.list; - for (; node; node = node->next) { - if (gc_isfixed(node) && gc_iswhite(node)) { - mark_gray(vm, node); - } - } -} - -static void mark_unscanned(bvm *vm) -{ - while (vm->gc.gray) { - bgcobject *obj = vm->gc.gray; - if (obj && !gc_isdark(obj) && !gc_isconst(obj)) { - gc_setdark(obj); - be_assert(!var_isstatic(obj)); - switch (var_primetype(obj)) { - case BE_CLASS: mark_class(vm, obj); break; - case BE_PROTO: mark_proto(vm, obj); break; - case BE_INSTANCE: mark_instance(vm, obj); break; - case BE_MAP: mark_map(vm, obj); break; - case BE_LIST: mark_list(vm, obj); break; - case BE_CLOSURE: mark_closure(vm, obj); break; - case BE_NTVCLOS: mark_ntvclos(vm, obj); break; - case BE_MODULE: mark_module(vm, obj); break; - default: - be_assert(0); /* error */ - break; - } - } - } -} - -static void destruct_object(bvm *vm, bgcobject *obj) -{ - if (vm->gc.status & GC_ALLOC) { - return; /* no destructor is called during the allocation. */ - } - if (obj->type == BE_INSTANCE) { - int type; - binstance *ins = cast_instance(obj); - /* does not GC when creating the string "deinit". */ - type = be_instance_member_simple(vm, ins, str_literal(vm, "deinit"), vm->top); - be_incrtop(vm); - if (basetype(type) == BE_FUNCTION) { - var_setinstance(vm->top, ins); /* push instance on stack as arg 1 */ - be_incrtop(vm); - be_dofunc(vm, vm->top - 2, 1); /* warning, there shoudln't be any exception raised here, or the gc stops */ - be_stackpop(vm, 1); - } - be_stackpop(vm, 1); - } -} - -static void destruct_white(bvm *vm) -{ - bgcobject *node = vm->gc.list; - /* since the destructor may allocate objects, we must first suspend the GC */ - vm->gc.status |= GC_HALT; /* mark GC is halt */ - while (node) { - if (gc_iswhite(node)) { - destruct_object(vm, node); - } - node = node->next; - } - vm->gc.status &= ~GC_HALT; /* reset GC halt flag */ -} - -static void delete_white(bvm *vm) -{ - bgcobject *node, *prev, *next; - for (node = vm->gc.list, prev = node; node; node = next) { - next = node->next; - if (gc_iswhite(node)) { - if (node == vm->gc.list) { /* first node */ - vm->gc.list = node->next; - prev = node->next; - } else { /* not first node */ - prev->next = next; - } - free_object(vm, node); -#if BE_USE_PERF_COUNTERS - vm->counter_gc_freed++; -#endif - } else { - gc_setwhite(node); - prev = node; - } - } -} - -static void reset_fixedlist(bvm *vm) -{ - bgcobject *node; - for (node = vm->gc.fixed; node; node = node->next) { - if (gc_isdark(node)) { - gc_setwhite(node); - } - } -} - -void be_gc_auto(bvm *vm) -{ - if (vm->gc.status & GC_PAUSE && (BE_USE_DEBUG_GC || vm->gc.usage > vm->gc.threshold || comp_is_gc_debug(vm))) { - be_gc_collect(vm); - } -} - -size_t be_gc_memcount(bvm *vm) -{ - return vm->gc.usage; -} - -#if BE_USE_PERF_COUNTERS -#define GC_TIMER(i) if (vm->microsfnct) { vm->micros_gc##i = vm->microsfnct(); } -#else -#define GC_TIMER(i) -#endif - -void be_gc_collect(bvm *vm) -{ - if (vm->gc.status & GC_HALT) { - return; /* the GC cannot run for some reason */ - } -#if BE_USE_PERF_COUNTERS - size_t slors_used_before_gc, slots_allocated_before_gc; - be_gc_memory_pools_info(vm, &slors_used_before_gc, &slots_allocated_before_gc); - vm->counter_gc_kept = 0; - vm->counter_gc_freed = 0; -#endif - if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_START, vm->gc.usage); - GC_TIMER(0); - /* step 1: set root-set reference objects to unscanned */ - mark_gray_reset_counters(vm); /* reset all internal counters */ - premark_internal(vm); /* object internal the VM */ - premark_global(vm); /* global objects */ - premark_stack(vm); /* stack objects */ - premark_tracestack(vm); /* trace stack objects */ - premark_fixed(vm); /* fixed objects */ - GC_TIMER(1); - /* step 2: set unscanned objects to black */ - mark_unscanned(vm); - GC_TIMER(2); - /* step 3: destruct and delete unreachable objects */ - destruct_white(vm); - delete_white(vm); - be_gcstrtab(vm); - GC_TIMER(3); - /* step 4: reset the fixed objects */ - reset_fixedlist(vm); - GC_TIMER(4); - /* step 5: calculate the next GC threshold */ - vm->gc.threshold = next_threshold(vm->gc); - be_gc_memory_pools(vm); /* free unsued memory pools */ - GC_TIMER(5); -#if BE_USE_PERF_COUNTERS - size_t slors_used_after_gc, slots_allocated_after_gc; - be_gc_memory_pools_info(vm, &slors_used_after_gc, &slots_allocated_after_gc); - if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_kept, vm->counter_gc_freed, - slors_used_before_gc, slots_allocated_before_gc, - slors_used_after_gc, slots_allocated_after_gc); -#else - if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage); -#endif -} diff --git a/lib/libesp32/Berry/src/be_gc.h b/lib/libesp32/Berry/src/be_gc.h deleted file mode 100644 index 1544041defa2..000000000000 --- a/lib/libesp32/Berry/src/be_gc.h +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_GC_H -#define BE_GC_H - -#include "be_object.h" - -#define gc_object(o) cast(bgcobject*, o) -#define gc_cast(o, t, T) ((o) && (o)->type == (t) ? (T*)(o) : NULL) -#define cast_proto(o) gc_cast(o, BE_PROTO, bproto) -#define cast_closure(o) gc_cast(o, BE_CLOSURE, bclosure) -#define cast_ntvclos(o) gc_cast(o, BE_NTVCLOS, bntvclos) -#define cast_str(o) gc_cast(o, BE_STRING, bstring) -#define cast_class(o) gc_cast(o, BE_CLASS, bclass) -#define cast_instance(o) gc_cast(o, BE_INSTANCE, binstance) -#define cast_map(o) gc_cast(o, BE_MAP, bmap) -#define cast_list(o) gc_cast(o, BE_LIST, blist) -#define cast_module(o) gc_cast(o, BE_MODULE, bmodule) - -#define gc_ismark(o, m) (((o)->marked & 0x03) == m) -#define gc_iswhite(o) gc_ismark((o), GC_WHITE) -#define gc_isgray(o) gc_ismark((o), GC_GRAY) -#define gc_isdark(o) gc_ismark((o), GC_DARK) - -#define gc_setmark(o, m) \ -if (!gc_isconst(o)) { \ - (o)->marked &= ~0x03; \ - (o)->marked |= (m) & 0x03; \ -} - -#define gc_setwhite(o) gc_setmark((o), GC_WHITE) -#define gc_setgray(o) gc_setmark((o), GC_GRAY) -#if BE_USE_PERF_COUNTERS - #define gc_setdark(o) { vm->counter_gc_kept++; gc_setmark((o), GC_DARK); } -#else - #define gc_setdark(o) gc_setmark((o), GC_DARK) -#endif -#define gc_isfixed(o) (((o)->marked & GC_FIXED) != 0) -#define gc_setfixed(o) ((o)->marked |= GC_FIXED) -#define gc_clearfixed(o) ((o)->marked &= ~GC_FIXED) -#define gc_isconst(o) (((o)->marked & GC_CONST) != 0) -#define gc_exmark(o) (((o)->marked >> 4) & 0x0F) -#define gc_setexmark(o, k) ((o)->marked |= (k) << 4) - -#define be_isgcobj(o) (var_primetype(o) >= BE_GCOBJECT && var_primetype(o) < BE_GCOBJECT_MAX) -#define be_gcnew(v, t, s) be_newgcobj((v), (t), sizeof(s)) - -#define set_fixed(s) bbool _was_fixed = be_gc_fix_set(vm, cast(bgcobject*, (s)), 1) -#define restore_fixed(s) be_gc_fix_set(vm, cast(bgcobject*, (s)), _was_fixed); - -/* the GC mark uses bit4:0 of the `object->marked` field, - * so other bits can be used for special flags (ex-mark). */ -typedef enum { - GC_WHITE = 0x00, /* unreachable object */ - GC_GRAY = 0x01, /* unscanned object */ - GC_DARK = 0x02, /* scanned object */ - GC_FIXED = 0x04, /* disable collection mark */ - GC_CONST = 0x08 /* constant object mark */ -} bgcmark; - -void be_gc_init(bvm *vm); -void be_gc_deleteall(bvm *vm); -void be_gc_setsteprate(bvm *vm, int rate); -void be_gc_setpause(bvm *vm, int pause); -size_t be_gc_memcount(bvm *vm); -bgcobject *be_newgcobj(bvm *vm, int type, size_t size); -bgcobject* be_gc_newstr(bvm *vm, size_t size, int islong); -void be_gc_fix(bvm *vm, bgcobject *obj); -void be_gc_unfix(bvm *vm, bgcobject *obj); -bbool be_gc_fix_set(bvm *vm, bgcobject *obj, bbool fix); -void be_gc_collect(bvm *vm); -void be_gc_auto(bvm *vm); - -#endif diff --git a/lib/libesp32/Berry/src/be_gclib.c b/lib/libesp32/Berry/src/be_gclib.c deleted file mode 100644 index 9ca9eab50597..000000000000 --- a/lib/libesp32/Berry/src/be_gclib.c +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_gc.h" - -#if BE_USE_GC_MODULE - -static int m_allocated(bvm *vm) -{ - size_t count = be_gc_memcount(vm); - if (count < 0x80000000) { - be_pushint(vm, (bint)count); - } else { - be_pushreal(vm, (breal)count); - } - be_return(vm); -} - -static int m_collect(bvm *vm) -{ - be_gc_collect(vm); - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(gc){ - be_native_module_function("allocated", m_allocated), - be_native_module_function("collect", m_collect) -}; - -be_define_native_module(gc, NULL); -#else -/* @const_object_info_begin -module gc (scope: global, depend: BE_USE_GC_MODULE) { - allocated, func(m_allocated) - collect, func(m_collect) -} -@const_object_info_end */ -#include "../generate/be_fixed_gc.h" -#endif - -#endif /* BE_USE_SYS_MODULE */ diff --git a/lib/libesp32/Berry/src/be_globallib.c b/lib/libesp32/Berry/src/be_globallib.c deleted file mode 100644 index 6597fe78ba23..000000000000 --- a/lib/libesp32/Berry/src/be_globallib.c +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2021 Guan Wenliang & Stephan Hadinger -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_module.h" -#include "be_string.h" -#include "be_vector.h" -#include "be_class.h" -#include "be_debug.h" -#include "be_map.h" -#include "be_vm.h" -#include "be_var.h" -#include - -#if BE_USE_GLOBAL_MODULE - -#define global(vm) ((vm)->gbldesc.global) - -static void dump_map_keys(bvm *vm, bmap *map) -{ - if (!map) { return; } /* protect agains potential null pointer */ - bmapnode *node; - bmapiter iter = be_map_iter(); - while ((node = be_map_next(map, &iter)) != NULL) { - if (var_isstr(&node->key)) { - bstring *s = var_tostr(&node->key); - be_pushstring(vm, str(s)); - be_data_push(vm, -2); - be_pop(vm, 1); - } - } -} - -static int m_globals(bvm *vm) -{ - be_newobject(vm, "list"); - dump_map_keys(vm, global(vm).vtab); - be_pop(vm, 1); - be_return(vm); -} - -static int m_contains(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1 && be_isstring(vm, 1)) { - const char * name = be_tostring(vm, 1); - int idx = be_global_find(vm, be_newstr(vm, name)); - be_pushbool(vm, idx > -1); - be_return(vm); - } - be_return_nil(vm); -} - -static int m_findglobal(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1 && be_isstring(vm, 1)) { - const char * name = be_tostring(vm, 1); - be_getglobal(vm, name); - be_return(vm); - } - be_return_nil(vm); -} - -static int m_setglobal(bvm *vm) -{ - int top = be_top(vm); - if (top >= 2 && be_isstring(vm, 1)) { - const char * name = be_tostring(vm, 1); - be_setglobal(vm, name); - } - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(global) { - be_native_module_function("()", m_globals), - be_native_module_function("contains", m_contains), - be_native_module_function("member", m_findglobal), - be_native_module_function("setmember", m_setglobal), -}; - -be_define_native_module(global, NULL); -#else -/* @const_object_info_begin -module global (scope: global, depend: BE_USE_GLOBAL_MODULE) { - (), func(m_globals) - contains, func(m_contains) - member, func(m_findglobal) - setmember, func(m_setglobal) -} -@const_object_info_end */ -#include "../generate/be_fixed_global.h" -#endif - -#endif /* BE_USE_GLOBAL_MODULE */ diff --git a/lib/libesp32/Berry/src/be_introspectlib.c b/lib/libesp32/Berry/src/be_introspectlib.c deleted file mode 100644 index 78e7eb0e5a11..000000000000 --- a/lib/libesp32/Berry/src/be_introspectlib.c +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_module.h" -#include "be_string.h" -#include "be_vector.h" -#include "be_class.h" -#include "be_debug.h" -#include "be_map.h" -#include "be_vm.h" -#include "be_exec.h" -#include "be_gc.h" -#include - -#if BE_USE_INTROSPECT_MODULE - -#define global(vm) ((vm)->gbldesc.global) -#define builtin(vm) ((vm)->gbldesc.builtin) - -static void dump_map_keys(bvm *vm, bmap *map) -{ - if (!map) { return; } /* protect agains potential null pointer */ - bmapnode *node; - bmapiter iter = be_map_iter(); - while ((node = be_map_next(map, &iter)) != NULL) { - if (var_isstr(&node->key)) { - bstring *s = var_tostr(&node->key); - be_pushstring(vm, str(s)); - be_data_push(vm, -2); - be_pop(vm, 1); - } - } -} - -static int m_attrlist(bvm *vm) -{ - int top = be_top(vm); - be_newobject(vm, "list"); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - void *obj = var_toobj(v); - switch (var_type(v)) { - case BE_NIL: dump_map_keys(vm, global(vm).vtab); break; - case BE_MODULE: dump_map_keys(vm, ((bmodule*)obj)->table); break; - case BE_CLASS: dump_map_keys(vm, ((bclass*)obj)->members); break; - case BE_INSTANCE: dump_map_keys(vm, ((binstance*)obj)->_class->members); break; - default: break; - } - } else { /* if no parameter, then dump globals */ - dump_map_keys(vm, global(vm).vtab); - } - be_pop(vm, 1); - be_return(vm); -} - -static void m_findmember_protected(bvm *vm, void* data) -{ - be_getmember(vm, 1, (const char*) data); -} - -static int m_findmember(bvm *vm) -{ - int top = be_top(vm); - bbool protected = btrue; /* run protected, i.e. don't raise an exception if not found */ - if (top >= 3) { - protected = !be_tobool(vm, 3); - } - if (top >= 2 && be_isstring(vm, 2)) { - if (protected) { - if (be_isinstance(vm, 1) || be_ismodule(vm, 1) || be_isclass(vm, 1)) { - int ret = be_execprotected(vm, &m_findmember_protected, (void*) be_tostring(vm, 2)); - if (ret == BE_OK) { - be_return(vm); - } - } - be_return_nil(vm); - } else { - /* run unprotected */ - if (be_getmember(vm, 1, be_tostring(vm, 2))) { - be_return(vm); - } else { - /* not found, return module 'undefined' */ - be_getmodule(vm, "undefined"); - be_return(vm); - } - } - } - be_return_nil(vm); -} - -static int m_contains(bvm *vm) -{ - bbool contains = bfalse; - int top = be_top(vm); - if (top >= 2 && be_isstring(vm, 2) && (be_isinstance(vm, 1) || be_ismodule(vm, 1) || be_isclass(vm, 1))) { - if (be_getmember(vm, 1, be_tostring(vm, 2))) { - contains = btrue; - } - } - be_pushbool(vm, contains); - be_return(vm); -} - -static int m_setmember(bvm *vm) -{ - int top = be_top(vm); - if (top >= 3 && (be_isinstance(vm, 1) || be_ismodule(vm, 1) || be_isclass(vm, 1)) && be_isstring(vm, 2)) { - be_setmember(vm, 1, be_tostring(vm, 2)); - be_return(vm); - } - be_return_nil(vm); -} - -static int m_toptr(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - if (var_type(v) == BE_STRING) { - be_pushcomptr(vm, (void*)be_tostring(vm, 1)); - be_return(vm); - } else if (var_basetype(v) >= BE_FUNCTION || var_type(v) == BE_COMPTR) { - be_pushcomptr(vm, var_toobj(v)); - be_return(vm); - } else if (var_type(v) == BE_INT) { - be_pushcomptr(vm, (void*) (intptr_t) var_toint(v)); - be_return(vm); - } else { - be_raise(vm, "value_error", "unsupported for this type"); - } - } - be_return_nil(vm); -} - -static int m_fromptr(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - void* v; - if (be_iscomptr(vm, 1)) { - v = be_tocomptr(vm, 1); - } else { - v = (void*) (intptr_t) be_toint(vm, 1); - } - if (v) { - bgcobject *ptr = (bgcobject*)v; - if (var_basetype(ptr) >= BE_GCOBJECT) { - bvalue *top = be_incrtop(vm); - var_setobj(top, ptr->type, ptr); - } else { - be_raise(vm, "value_error", "unsupported for this type"); - } - be_return(vm); - } - } - be_return_nil(vm); -} - -/* load module by name, like `import` would do. But don't create a global variable from it. */ -static int m_getmodule(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - if (var_isstr(v)) { - int ret = be_module_load(vm, var_tostr(v)); - if (ret == BE_OK) { - be_return(vm); - } - } - } - be_return_nil(vm); -} - -/* set or chang the cached value for the named module, this allows monkey patching. **USE WITH CARE** */ -static int m_setmodule(bvm *vm) -{ - int top = be_top(vm); - if (top >= 2) { - bvalue *v = be_indexof(vm, 1); - if (var_isstr(v)) { - be_pushvalue(vm, 2); /* ensure the second arg is at top of stack */ - be_cache_module(vm, var_tostr(v)); - } - } - be_return_nil(vm); -} - -/* checks if the function (berry bytecode bproto only) is hinted as a method */ -static int m_ismethod(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - if (var_isclosure(v)) { - bclosure *cl = var_toobj(v); - bproto *pr = cl->proto; - be_pushbool(vm, pr->varg & BE_VA_METHOD); - be_return(vm); - } - } - be_return_nil(vm); -} - -static int m_name(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - const char* name = NULL; - switch (var_type(v)) { - case BE_CLOSURE: - name = str(((bclosure*) var_toobj(v))->proto->name); - break; - case BE_CLASS: - name = str(((bclass*) var_toobj(v))->name); - break; - case BE_MODULE: - name = be_module_name(var_toobj(v)); - break; - } - if (name) { - be_pushstring(vm, name); - be_return(vm); - } - } - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(introspect) { - be_native_module_function("members", m_attrlist), - - be_native_module_function("get", m_findmember), - be_native_module_function("set", m_setmember), - be_native_module_function("contains", m_contains), - - be_native_module_function("module", m_getmodule), - be_native_module_function("setmodule", m_setmodule), - - be_native_module_function("toptr", m_toptr), - be_native_module_function("fromptr", m_fromptr), - - be_native_module_function("name", m_name), - - be_native_module_function("ismethod", m_ismethod), -}; - -be_define_native_module(introspect, NULL); -#else -/* @const_object_info_begin -module introspect (scope: global, depend: BE_USE_INTROSPECT_MODULE) { - members, func(m_attrlist) - - get, func(m_findmember) - set, func(m_setmember) - contains, func(m_contains) - - module, func(m_getmodule) - setmodule, func(m_setmodule) - - toptr, func(m_toptr) - fromptr, func(m_fromptr) - - name, func(m_name) - - ismethod, func(m_ismethod) -} -@const_object_info_end */ -#include "../generate/be_fixed_introspect.h" -#endif - -#endif /* BE_USE_INTROSPECT_MODULE */ diff --git a/lib/libesp32/Berry/src/be_jsonlib.c b/lib/libesp32/Berry/src/be_jsonlib.c deleted file mode 100644 index 615e8bebcfa1..000000000000 --- a/lib/libesp32/Berry/src/be_jsonlib.c +++ /dev/null @@ -1,565 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_mem.h" -#include -#include - -#if BE_USE_JSON_MODULE - -#define MAX_INDENT 24 -#define INDENT_WIDTH 2 -#define INDENT_CHAR ' ' - -static const char* parser_value(bvm *vm, const char *json); -static void value_dump(bvm *vm, int *indent, int idx, int fmt); - -static const char* skip_space(const char *s) -{ - int c; - while (((c = *s) != '\0') && ((c == ' ') - || (c == '\t') || (c == '\r') || (c == '\n'))) { - ++s; - } - return s; -} - -static int is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -static const char* match_char(const char *json, int ch) -{ - json = skip_space(json); - if (*json == ch) { - return skip_space(json + 1); - } - return NULL; -} - -static int is_object(bvm *vm, const char *class, int idx) -{ - if (be_isinstance(vm, idx)) { - be_pushvalue(vm, idx); - while (1) { - be_getsuper(vm, -1); - if (be_isnil(vm, -1)) { - be_pop(vm, 1); - break; - } - be_remove(vm, -2); - } - const char *name = be_classname(vm, -1); - bbool ret = !strcmp(name, class); - be_pop(vm, 1); - return ret; - } - return 0; -} - -static int json_strlen(const char *json) -{ - int ch; - const char *s = json + 1; /* skip '"' */ - /* get string length "(\\.|[^"])*" */ - while ((ch = *s) != '\0' && ch != '"') { - ++s; - if (ch == '\\') { - ch = *s++; - if (ch == '\0') { - return -1; - } - } - } - return ch ? cast_int(s - json - 1) : -1; -} - -static void json2berry(bvm *vm, const char *class) -{ - be_getbuiltin(vm, class); - be_pushvalue(vm, -2); - be_call(vm, 1); - be_moveto(vm, -2, -3); - be_pop(vm, 2); -} - -static const char* parser_true(bvm *vm, const char *json) -{ - if (!strncmp(json, "true", 4)) { - be_pushbool(vm, btrue); - return json + 4; - } - return NULL; -} - -static const char* parser_false(bvm *vm, const char *json) -{ - if (!strncmp(json, "false", 5)) { - be_pushbool(vm, bfalse); - return json + 5; - } - return NULL; -} - -static const char* parser_null(bvm *vm, const char *json) -{ - if (!strncmp(json, "null", 4)) { - be_pushnil(vm); - return json + 4; - } - return NULL; -} - -static char* load_unicode(char *dst, const char *json) -{ - int ucode = 0, i = 4; - while (i--) { - int ch = *json++; - if (ch >= '0' && ch <= '9') { - ucode = (ucode << 4) | (ch - '0'); - } else if (ch >= 'A' && ch <= 'F') { - ucode = (ucode << 4) | (ch - 'A' + 0x0A); - } else if (ch >= 'a' && ch <= 'f') { - ucode = (ucode << 4) | (ch - 'a' + 0x0A); - } else { - return NULL; - } - } - /* convert unicode to utf8 */ - if (ucode < 0x007F) { - /* unicode: 0000 - 007F -> utf8: 0xxxxxxx */ - *dst++ = (char)(ucode & 0x7F); - } else if (ucode < 0x7FF) { - /* unicode: 0080 - 07FF -> utf8: 110xxxxx 10xxxxxx */ - *dst++ = (char)(((ucode >> 6) & 0x1F) | 0xC0); - *dst++ = (char)((ucode & 0x3F) | 0x80); - } else { - /* unicode: 0800 - FFFF -> utf8: 1110xxxx 10xxxxxx 10xxxxxx */ - *dst++ = (char)(((ucode >> 12) & 0x0F) | 0xE0); - *dst++ = (char)(((ucode >> 6) & 0x03F) | 0x80); - *dst++ = (char)((ucode & 0x3F) | 0x80); - } - return dst; -} - -static const char* parser_string(bvm *vm, const char *json) -{ - if (*json == '"') { - int len = json_strlen(json++); - if (len > -1) { - int ch; - char *buf, *dst = buf = be_malloc(vm, len); - while ((ch = *json) != '\0' && ch != '"') { - ++json; - if (ch == '\\') { - ch = *json++; /* skip '\' */ - switch (ch) { - case '"': *dst++ = '"'; break; - case '\\': *dst++ = '\\'; break; - case '/': *dst++ = '/'; break; - case 'b': *dst++ = '\b'; break; - case 'f': *dst++ = '\f'; break; - case 'n': *dst++ = '\n'; break; - case 'r': *dst++ = '\r'; break; - case 't': *dst++ = '\t'; break; - case 'u': { /* load unicode */ - dst = load_unicode(dst, json); - if (dst == NULL) { - be_free(vm, buf, len); - return NULL; - } - json += 4; - break; - } - default: be_free(vm, buf, len); return NULL; /* error */ - } - } else if(ch >= 0 && ch <= 0x1f) { - /* control characters must be escaped - as per https://www.rfc-editor.org/rfc/rfc7159#section-7 */ - be_free(vm, buf, len); - return NULL; - } else { - *dst++ = (char)ch; - } - } - be_assert(ch == '"'); - /* require the stack to have some free space for the string, - since parsing deeply nested objects might - crash the VM due to insufficient stack space. */ - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - be_pushnstring(vm, buf, cast_int(dst - buf)); - be_free(vm, buf, len); - return json + 1; /* skip '"' */ - } - } - return NULL; -} - -static const char* parser_field(bvm *vm, const char *json) -{ - be_stack_require(vm, 2 + BE_STACK_FREE_MIN); - if (json && *json == '"') { - json = parser_string(vm, json); - if (json) { - json = match_char(json, ':'); - if (json) { - json = parser_value(vm, json); - if (json) { - be_data_insert(vm, -3); - be_pop(vm, 2); /* pop key and value */ - return json; - } - } - be_pop(vm, 1); /* pop key */ - } - } - return NULL; -} - -static const char* parser_object(bvm *vm, const char *json) -{ - json = match_char(json, '{'); - be_newmap(vm); - if (*json != '}') { - const char *s; - json = parser_field(vm, json); - if (json == NULL) { - be_pop(vm, 1); /* pop map */ - return NULL; - } - while ((s = match_char(json, ',')) != NULL) { - json = parser_field(vm, s); - if (json == NULL) { - be_pop(vm, 1); /* pop map */ - return NULL; - } - } - } - if ((json = match_char(json, '}')) == NULL) { - be_pop(vm, 1); /* pop map */ - return NULL; - } - json2berry(vm, "map"); - return json; -} - -static const char* parser_array(bvm *vm, const char *json) -{ - json = match_char(json, '['); - be_newlist(vm); - if (*json != ']') { - const char *s; - json = parser_value(vm, json); - if (json == NULL) { - be_pop(vm, 1); /* pop map */ - return NULL; - } - be_data_push(vm, -2); - be_pop(vm, 1); /* pop value */ - while ((s = match_char(json, ',')) != NULL) { - json = parser_value(vm, s); - if (json == NULL) { - be_pop(vm, 1); /* pop map */ - return NULL; - } - be_data_push(vm, -2); - be_pop(vm, 1); /* pop value */ - } - } - if ((json = match_char(json, ']')) == NULL) { - be_pop(vm, 1); /* pop map */ - return NULL; - } - json2berry(vm, "list"); - return json; -} - -static const char* parser_number(bvm *vm, const char *json) -{ - char c = *json++; - bbool is_neg = c == '-'; - if(is_neg) { - c = *json++; - if(!is_digit(c)) { - /* minus must be followed by digit */ - return NULL; - } - } - bint intv = 0; - if(c != '0') { - /* parse integer part */ - while(is_digit(c)) { - intv = intv * 10 + c - '0'; - c = *json++; - } - - } else { - /* - Number starts with zero, this is only allowed - if the number is just '0' or - it has a fractional part or exponent. - */ - c = *json++; - - } - if(c != '.' && c != 'e' && c != 'E') { - /* - No fractional part or exponent follows, this is an integer. - If digits follow after it (for example due to a leading zero) - this will cause an error in the calling function. - */ - be_pushint(vm, intv * (is_neg ? -1 : 1)); - json--; - return json; - } - breal realval = (breal) intv; - if(c == '.') { - - breal deci = 0.0, point = 0.1; - /* fractional part */ - c = *json++; - if(!is_digit(c)) { - /* decimal point must be followed by digit */ - return NULL; - } - while (is_digit(c)) { - deci = deci + ((breal)c - '0') * point; - point *= (breal)0.1; - c = *json++; - } - - realval += deci; - } - if(c == 'e' || c == 'E') { - c = *json++; - /* exponent part */ - breal ratio = c == '-' ? (breal)0.1 : 10; - if (c == '+' || c == '-') { - c = *json++; - if(!is_digit(c)) { - return NULL; - } - } - if(!is_digit(c)) { - /* e and sign must be followed by digit */ - return NULL; - } - unsigned int e = 0; - while (is_digit(c)) { - e = e * 10 + c - '0'; - c = *json++; - } - /* e > 0 must be here to prevent infinite loops when e overflows */ - while (e--) { - realval *= ratio; - } - } - - be_pushreal(vm, realval * (is_neg ? -1.0 : 1.0)); - json--; - return json; -} - -/* parser json value */ -static const char* parser_value(bvm *vm, const char *json) -{ - json = skip_space(json); - /* - Each value will push at least one thig to the stack, so we must ensure it's big enough. - We need to take special care to extend the stack in values which have variable length (arrays and objects) - */ - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - switch (*json) { - case '{': /* object */ - return parser_object(vm, json); - case '[': /* array */ - return parser_array(vm, json); - case '"': /* string */ - return parser_string(vm, json); - case 't': /* true */ - return parser_true(vm, json); - case 'f': /* false */ - return parser_false(vm, json); - case 'n': /* null */ - return parser_null(vm, json); - default: /* number */ - if (*json == '-' || is_digit(*json)) { - return parser_number(vm, json); - } - } - return NULL; -} - -static int m_json_load(bvm *vm) -{ - if (be_isstring(vm, 1)) { - const char *json = be_tostring(vm, 1); - json = parser_value(vm, json); - if (json != NULL && *json == '\0') { - be_return(vm); - } - } - be_return_nil(vm); -} - -static void make_indent(bvm *vm, int stridx, int indent) -{ - if (indent) { - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - char buf[MAX_INDENT * INDENT_WIDTH + 1]; - indent = (indent < MAX_INDENT ? indent : MAX_INDENT) * INDENT_WIDTH; - memset(buf, INDENT_CHAR, indent); - buf[indent] = '\0'; - stridx = be_absindex(vm, stridx); - be_pushstring(vm, buf); - be_strconcat(vm, stridx); - be_pop(vm, 1); - } -} - -void string_dump(bvm *vm, int index) -{ - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - be_tostring(vm, index); /* convert value to string */ - be_toescape(vm, index, 'u'); - be_pushvalue(vm, index); -} - -static void object_dump(bvm *vm, int *indent, int idx, int fmt) -{ - - be_stack_require(vm, 3 + BE_STACK_FREE_MIN); /* 3 pushes outside the loop */ - be_getmember(vm, idx, ".p"); - be_pushstring(vm, fmt ? "{\n" : "{"); - be_pushiter(vm, -2); /* map iterator use 1 register */ - *indent += fmt; - while (be_iter_hasnext(vm, -3)) { - be_stack_require(vm, 3 + BE_STACK_FREE_MIN); /* 3 pushes inside the loop */ - make_indent(vm, -2, fmt ? *indent : 0); - be_iter_next(vm, -3); - /* key.tostring() */ - string_dump(vm, -2); - be_strconcat(vm, -5); - be_pop(vm, 1); - be_pushstring(vm, fmt ? ": " : ":"); /* add ': ' */ - be_strconcat(vm, -5); - be_pop(vm, 1); - /* value.tostring() */ - value_dump(vm, indent, -1, fmt); - be_strconcat(vm, -5); - be_pop(vm, 3); - if (be_iter_hasnext(vm, -3)) { - be_pushstring(vm, fmt ? ",\n" : ","); - be_strconcat(vm, -3); - be_pop(vm, 1); - } else if (fmt) { - be_pushstring(vm, "\n"); - be_strconcat(vm, -3); - be_pop(vm, 1); - } - } - *indent -= fmt; - be_pop(vm, 1); /* pop iterator */ - make_indent(vm, -1, fmt ? *indent : 0); - be_pushstring(vm, "}"); - be_strconcat(vm, -2); - be_moveto(vm, -2, -3); - be_pop(vm, 2); -} - -static void array_dump(bvm *vm, int *indent, int idx, int fmt) -{ - be_stack_require(vm, 3 + BE_STACK_FREE_MIN); - be_getmember(vm, idx, ".p"); - be_pushstring(vm, fmt ? "[\n" : "["); - be_pushiter(vm, -2); - *indent += fmt; - while (be_iter_hasnext(vm, -3)) { - make_indent(vm, -2, fmt ? *indent : 0); - be_iter_next(vm, -3); - value_dump(vm, indent, -1, fmt); - be_strconcat(vm, -4); - be_pop(vm, 2); - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - if (be_iter_hasnext(vm, -3)) { - be_pushstring(vm, fmt ? ",\n" : ","); - be_strconcat(vm, -3); - be_pop(vm, 1); - } else if (fmt) { - be_pushstring(vm, "\n"); - be_strconcat(vm, -3); - be_pop(vm, 1); - } - } - *indent -= fmt; - be_pop(vm, 1); /* pop iterator */ - make_indent(vm, -1, fmt ? *indent : 0); - be_pushstring(vm, "]"); - be_strconcat(vm, -2); - be_moveto(vm, -2, -3); - be_pop(vm, 2); -} - -static void value_dump(bvm *vm, int *indent, int idx, int fmt) -{ - // be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - if (is_object(vm, "map", idx)) { /* convert to json object */ - object_dump(vm, indent, idx, fmt); - } else if (is_object(vm, "list", idx)) { /* convert to json array */ - array_dump(vm, indent, idx, fmt); - } else if (be_isnil(vm, idx)) { /* convert to json null */ - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - be_pushstring(vm, "null"); - } else if (be_isreal(vm, idx)) { - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - breal v = be_toreal(vm, idx); - if (isnan(v) || isinf(v)) { - be_pushstring(vm, "null"); - } else { - be_tostring(vm, idx); - be_pushvalue(vm, idx); /* push to top */ - }; - } else if (be_isnumber(vm, idx) || be_isbool(vm, idx)) { /* convert to json number and boolean */ - be_stack_require(vm, 1 + BE_STACK_FREE_MIN); - be_tostring(vm, idx); - be_pushvalue(vm, idx); /* push to top */ - } else { /* convert to string */ - string_dump(vm, idx); - } -} - -static int m_json_dump(bvm *vm) -{ - int indent = 0, argc = be_top(vm); - int fmt = 0; - if (argc > 1) { - fmt = !strcmp(be_tostring(vm, 2), "format"); - } - value_dump(vm, &indent, 1, fmt); - be_return(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(json) { - be_native_module_function("load", m_json_load), - be_native_module_function("dump", m_json_dump) -}; - -be_define_native_module(json, NULL); -#else -/* @const_object_info_begin -module json (scope: global, depend: BE_USE_JSON_MODULE) { - load, func(m_json_load) - dump, func(m_json_dump) -} -@const_object_info_end */ -#include "../generate/be_fixed_json.h" -#endif - -#endif /* BE_USE_JSON_MODULE */ diff --git a/lib/libesp32/Berry/src/be_lexer.c b/lib/libesp32/Berry/src/be_lexer.c deleted file mode 100644 index 4e41bf8f61c4..000000000000 --- a/lib/libesp32/Berry/src/be_lexer.c +++ /dev/null @@ -1,871 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_lexer.h" -#include "be_string.h" -#include "be_mem.h" -#include "be_gc.h" -#include "be_exec.h" -#include "be_map.h" -#include "be_vm.h" -#include "be_strlib.h" -#include - -#define SHORT_STR_LEN 32 -#define EOS '\0' /* end of source */ - -#define type_count() (int)array_count(kwords_tab) -#define lexbuf(lex) ((lex)->buf.s) -#define isvalid(lex) ((lex)->reader.cursor < (lex)->endbuf) -#define lgetc(lex) ((lex)->reader.cursor) -#define setstr(lex, v) ((lex)->token.u.s = (v)) -#define setint(lex, v) ((lex)->token.u.i = (v)) -#define setreal(lex, v) ((lex)->token.u.r = (v)) -#define match(lex, pattern) while (pattern(lgetc(lex))) { save(lex); } - -#if BE_USE_SCRIPT_COMPILER - -/* IMPORTANT: This must follow the enum found in be_lexer.h !!! */ -static const char* const kwords_tab[] = { - "NONE", "EOS", "ID", "INT", "REAL", "STR", - "=", "+=","-=", "*=", "/=", "%=", "&=", "|=", - "^=", "<<=", ">>=", "+", "-", "*", "/", "%", - "<", "<=", "==", "!=", ">", ">=", "&", "|", - "^", "<<", ">>", "..", "&&", "||", "!", "~", - "(", ")", "[", "]", "{", "}", ".", ",", ";", - ":", "?", "->", "if", "elif", "else", "while", - "for", "def", "end", "class", "break", "continue", - "return", "true", "false", "nil", "var", "do", - "import", "as", "try", "except", "raise", "static", - ":=", -}; - -void be_lexerror(blexer *lexer, const char *msg) -{ - bvm *vm = lexer->vm; - const char *error = be_pushfstring(vm, - "%s:%d: %s", lexer->fname, lexer->linenumber, msg); - be_lexer_deinit(lexer); - be_raise(vm, "syntax_error", error); -} - -static void keyword_registe(bvm *vm) -{ - int i; - for (i = KeyIf; i < type_count(); ++i) { - bstring *s = be_newstr(vm, kwords_tab[i]); - be_gc_fix(vm, gc_object(s)); - be_str_setextra(s, i); - } -} - -static void keyword_unregiste(bvm *vm) -{ - int i; - for (i = KeyIf; i < type_count(); ++i) { - bstring *s = be_newstr(vm, kwords_tab[i]); - be_gc_unfix(vm, gc_object(s)); - } -} - -static bstring* cache_string(blexer *lexer, bstring *s) -{ - bvalue *res; - bvm *vm = lexer->vm; - var_setstr(vm->top, s); - be_stackpush(vm); /* cache string to stack */ - res = be_map_findstr(lexer->vm, lexer->strtab, s); - if (res) { - s = var_tostr(&be_map_val2node(res)->key); - } else { - res = be_map_insertstr(vm, lexer->strtab, s, NULL); - var_setnil(res); - } - be_stackpop(vm, 1); /* pop string frome stack */ - return s; -} - -static bstring* lexer_newstrn(blexer *lexer, const char *str, size_t len) -{ - return cache_string(lexer, be_newstrn(lexer->vm, str, len)); -} - -bstring* be_lexer_newstr(blexer *lexer, const char *str) -{ - return cache_string(lexer, be_newstr(lexer->vm, str)); -} - -static int next(blexer *lexer) -{ - struct blexerreader *lr = &lexer->reader; - if (!(lr->len--)) { - static const char eos = EOS; - const char *s = lr->readf(lexer, lr->data, &lr->len); - lr->s = s ? s : &eos; - --lr->len; - } - lexer->reader.cursor = *lr->s++; - return lexer->reader.cursor; -} - -static void clear_buf(blexer *lexer) -{ - lexer->buf.len = 0; -} - -static void save_char(blexer *lexer, int ch) { - struct blexerbuf *buf = &lexer->buf; - if (buf->len >= buf->size) { - size_t size = buf->size << 1; - buf->s = be_realloc(lexer->vm, buf->s, buf->size, size); - buf->size = size; - } - buf->s[buf->len++] = (char)ch; -} - -/* save and next */ -static int save(blexer *lexer) -{ - int ch = lgetc(lexer); - save_char(lexer, ch); - return next(lexer); -} - -static bstring* buf_tostr(blexer *lexer) -{ - struct blexerbuf *buf = &lexer->buf; - return lexer_newstrn(lexer, buf->s, buf->len); -} - -static int is_newline(int c) -{ - return c == '\n' || c == '\r'; -} - -static int is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -static int is_octal(int c) -{ - return c >= '0' && c <= '7'; -} - -static int is_letter(int c) -{ - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_'); -} - -static int is_word(int c) -{ - return is_letter(c) || is_digit(c); -} - -static int check_next(blexer *lexer, int c) -{ - if (lgetc(lexer) == c) { - next(lexer); - return 1; - } - return 0; -} - -static int check2hex(blexer *lexer, int c) -{ - c = be_char2hex(c); - if (c < 0) { - be_lexerror(lexer, "invalid hexadecimal number"); - } - return c; -} - -static int read_hex(blexer *lexer, const char *src) -{ - int c = check2hex(lexer, *src++); - return ((unsigned)c << 4) + check2hex(lexer, *src); -} - -static int read_oct(blexer *lexer, const char *src) -{ - int c = 0; - const char *end = src + 3; - while (src < end && is_octal(*src)) { - c = 8 * c + *src++ - '0'; - } - if (src < end) { - be_lexerror(lexer, "invalid octal number"); - } - return c; -} - -static void tr_string(blexer *lexer) -{ - char *dst, *src, *end; - dst = src = lexbuf(lexer); - end = lexbuf(lexer) + lexer->buf.len; - while (src < end) { - int c = *src++; - switch (c) { - case '\n': case '\r': - be_lexerror(lexer, "unfinished string"); - break; - case '\\': - switch (*src) { - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case '\\': c = '\\'; break; - case '\'': c = '\''; break; - case '"': c = '"'; break; - case '?': c = '?'; break; - case 'x': c = read_hex(lexer, ++src); ++src; break; - default: - c = read_oct(lexer, src); - if (c != EOS) { - src += 2; - } - break; - } - ++src; - break; - default: - break; - } - *dst++ = (char)c; - } - lexer->buf.len = dst - lexbuf(lexer); -} - -static int skip_newline(blexer *lexer) -{ - int lc = lgetc(lexer); - next(lexer); - if (is_newline(lgetc(lexer)) && lgetc(lexer) != lc) { - next(lexer); /* skip "\n\r" or "\r\n" */ - } - lexer->linenumber++; - return lexer->reader.cursor; -} - -static void skip_comment(blexer *lexer) -{ - next(lexer); /* skip '#' */ - if (lgetc(lexer) == '-') { /* mult-line comment */ - int lno = lexer->linenumber; - int mark, c = 'x'; /* skip first '-' (#- ... -#) */ - do { - mark = c == '-'; - if (is_newline(c)) { - c = skip_newline(lexer); - continue; - } - c = next(lexer); - } while (!(mark && c == '#') && c != EOS); - if (c == EOS) { - be_lexerror(lexer, be_pushfstring(lexer->vm, "unterminated comment block started in line %d", lno)); - } - next(lexer); /* skip '#' */ - } else { /* line comment */ - while (!is_newline(lgetc(lexer)) && lgetc(lexer)) { - next(lexer); - } - } -} - -static bbool scan_realexp(blexer *lexer) -{ - int c = lgetc(lexer); - if (c == 'e' || c == 'E') { - c = save(lexer); - if (c == '+' || c == '-') { - c = save(lexer); - } - if (!is_digit(c)) { - be_lexerror(lexer, "malformed number"); - } - match(lexer, is_digit); - return btrue; - } - return bfalse; -} - -static btokentype scan_dot_real(blexer *lexer) -{ - if (save(lexer) == '.') { /* is '..' */ - next(lexer); - return OptConnect; - } - if (is_digit(lgetc(lexer))) { - match(lexer, is_digit); - scan_realexp(lexer); - setreal(lexer, be_str2real(lexbuf(lexer), NULL)); - return TokenReal; - } - return OptDot; -} - -/* check the dots is a decimal dot or '..' operator */ -static bbool decimal_dots(blexer *lexer) -{ - if (lgetc(lexer) == '.') { /* '..' or real */ - if (save(lexer) != '.') { /* read numberic => \.\b* */ - match(lexer, is_digit); /* match and skip numberic */ - return btrue; - } - /* token '..' */ - next(lexer); /* skip the second '.' */ - lexer->cacheType = OptConnect; - } - return bfalse; /* operator '..' */ -} - -static bint scan_hexadecimal(blexer *lexer) -{ - bint res = 0; - int dig, num = 0; - while ((dig = be_char2hex(lgetc(lexer))) >= 0) { - res = ((bint)res << 4) + dig; - next(lexer); - ++num; - } - if (num == 0) { - be_lexerror(lexer, "invalid hexadecimal number"); - } - return res; -} - -static btokentype scan_decimal(blexer *lexer) -{ - btokentype type = TokenInteger; - match(lexer, is_digit); - /* decimal_dots() and scan_realexp() have side effect, so we call each explicitly */ - /* to prevent binary shortcut if the first is true */ - bbool has_decimal_dots = decimal_dots(lexer); - bbool is_realexp = scan_realexp(lexer); - if (has_decimal_dots || is_realexp) { - type = TokenReal; - } - /* use save_char to add the null terminator, */ - /* since it handles expanding the buffer if needed. */ - save_char(lexer, '\0'); - if (type == TokenReal) { - setreal(lexer, be_str2real(lexbuf(lexer), NULL)); - } else { - setint(lexer, be_str2int(lexbuf(lexer), NULL)); - } - return type; -} - -static btokentype scan_numeral(blexer *lexer) -{ - btokentype type = TokenInteger; - int c0 = lgetc(lexer), c1 = save(lexer); - /* hex: 0[xX][0-9a-fA-F]+ */ - if (c0 == '0' && (c1 == 'x' || c1 == 'X')) { - next(lexer); - setint(lexer, scan_hexadecimal(lexer)); - } else { - type = scan_decimal(lexer); - } - /* can't follow decimal or letter after numeral */ - if (lexer->cacheType == TokenNone) { - if (is_letter(lgetc(lexer)) || decimal_dots(lexer)) { - be_lexerror(lexer, "malformed number"); - } - } - return type; -} - -/* structure for a temporary reader used by transpiler, with attributes for an allocated buffer and size */ -struct blexerreader_save { - struct blexerreader reader; - char* s; - size_t size; - char cursor; -}; - -/* buf reader for transpiled code from f-strings */ -/* it restores the original reader when the transpiler buffer is empty */ -/* the first pass returns a single byte buffer with the saved cursor */ -/* the second pass restores the original reader */ -static const char* _bufgets(struct blexer* lexer, void *data, size_t *size) -{ - /* this is called once the temporaty transpiler buffer is empty */ - struct blexerreader *reader = &lexer->reader; /* current reader which is temporary only for the transpiler */ - struct blexerreader_save *reader_save = data; /* original reader that needs to be restored once the buffer is empty */ - - /* first case, we saved the cursor (fist char), we server it now */ - if (reader_save->reader.cursor >= 0) { /* serve the previously saved cursor */ - /* copy cursor to a 'char' type */ - reader_save->cursor = reader_save->reader.cursor; - reader_save->reader.cursor = -1; /* no more cursor saved */ - *size = 1; - return &reader_save->cursor; - } - - /* second case, the saved cursor was returned, now restore the normal flow of the original reader */ - /* restore the original reader */ - *reader = reader_save->reader; - - /* free the memory from the structure */ - be_free(lexer->vm, reader_save->s, reader_save->size); /* free the buffer */ - be_free(lexer->vm, reader_save, sizeof(struct blexerreader_save)); /* free the structure */ - - if (!reader->len) { /* just in case the original buffer was also */ - return reader->readf(lexer, reader->data, size); - } - /* the following is not necessary, but safer */ - *size = reader->len; - return reader->s; -} - -static btokentype scan_string(blexer *lexer); /* forward declaration */ - -/* scan f-string and transpile it to `format(...)` syntax then feeding the normal lexer and parser */ -static void scan_f_string(blexer *lexer) -{ - char ch = '\0'; - clear_buf(lexer); - scan_string(lexer); /* first scan the entire string in lexer->buf */ - - /* save original reader until the transpiled is processed */ - /* reader will be restored by the reader function once the transpiled buffer is empty */ - struct blexerreader_save *reader_save = (struct blexerreader_save *) be_malloc(lexer->vm, sizeof(struct blexerreader_save)); /* temporary reader */ - reader_save->reader = lexer->reader; - - /* save blexerbuf which contains the unparsed_fstring */ - struct blexerbuf buf_unparsed_fstr = lexer->buf; - - /* prepare and allocated a temporary buffer to save parsed f_string */ - lexer->buf.size = lexer->buf.size + 20; - lexer->buf.s = be_malloc(lexer->vm, lexer->buf.size); - lexer->buf.len = 0; - - /* parse f_string */ - /* First pass, check syntax and extract string literals, and format */ - save_char(lexer, '('); - save_char(lexer, '"'); - for (size_t i = 0; i < buf_unparsed_fstr.len; i++) { - ch = buf_unparsed_fstr.s[i]; - switch (ch) { - case '%': /* % needs to be encoded as %% */ - save_char(lexer, '%'); - save_char(lexer, '%'); - break; - case '\\': /* \ needs to be encoded as \\ */ - save_char(lexer, '\\'); - save_char(lexer, '\\'); - break; - case '"': /* " needs to be encoded as \" */ - save_char(lexer, '\\'); - save_char(lexer, '"'); - break; - case '}': /* }} is converted as } yet we tolerate a single } */ - if ((i+1 < buf_unparsed_fstr.len) && (buf_unparsed_fstr.s[i+1] == '}')) { i++; } /* if '}}' replace with '}' */ - save_char(lexer, '}'); - break; - case '\n': - save_char(lexer, '\\'); - save_char(lexer, 'n'); - break; - case '\r': - save_char(lexer, '\\'); - save_char(lexer, 'r'); - break; - default: /* copy any other character */ - save_char(lexer, ch); - break; - case '{': /* special case for { */ - i++; /* in all cases skip to next char */ - if ((i < buf_unparsed_fstr.len) && (buf_unparsed_fstr.s[i] == '{')) { - save_char(lexer, '{'); /* {{ is simply encoded as { and continue parsing */ - } else { - /* we still don't know if '=' is present, so we copy the expression each time, and rollback if we find out the '=' is not present */ - size_t rollback = lexer->buf.len; /* mark the end of string for later rollback if '=' is not present */ - /* parse inner part */ - /* skip everything until either ':' or '}' or '=' */ - /* if end of string is reached before '}' raise en error */ - for (; i < buf_unparsed_fstr.len; i++) { - ch = buf_unparsed_fstr.s[i]; - if (ch == ':' || ch == '}') { break; } - save_char(lexer, ch); /* copy any character unless it's ':' or '}' */ - if (ch == '=') { break; } /* '=' is copied but breaks parsing as well */ - } - /* safe check if we reached the end of the string */ - if (i >= buf_unparsed_fstr.len) { be_raise(lexer->vm, "syntax_error", "'}' expected"); } - /* if '=' detected then do some additional checks */ - if (ch == '=') { - i++; /* skip '=' and check we haven't reached the end */ - if (i >= buf_unparsed_fstr.len) { be_raise(lexer->vm, "syntax_error", "'}' expected"); } - ch = buf_unparsed_fstr.s[i]; - if ((ch != ':') && (ch != '}')) { /* '=' must be immediately followed by ':' or '}' */ - be_raise(lexer->vm, "syntax_error", "':' or '}' expected after '='"); - } - } else { - /* no '=' present, rollback the text of the expression */ - lexer->buf.len = rollback; - } - save_char(lexer, '%'); /* start format encoding */ - if (ch == ':') { - /* copy format */ - i++; - if ((i < buf_unparsed_fstr.len) && (buf_unparsed_fstr.s[i] == '%')) { i++; } /* skip '%' following ':' */ - for (; i < buf_unparsed_fstr.len; i++) { - ch = buf_unparsed_fstr.s[i]; - if (ch == '}') { break; } - save_char(lexer, ch); - } - if (i >= buf_unparsed_fstr.len) { be_raise(lexer->vm, "syntax_error", "'}' expected"); } - } else { - /* if no formatting, output '%s' */ - save_char(lexer, 's'); - } - } - break; - } - } - save_char(lexer, '"'); /* finish format string */ - - /* Second pass - add arguments if any */ - for (size_t i = 0; i < buf_unparsed_fstr.len; i++) { - /* skip any character that is not '{' followed by '{' */ - if (buf_unparsed_fstr.s[i] == '{') { - i++; /* in all cases skip to next char */ - if ((i < buf_unparsed_fstr.len) && (buf_unparsed_fstr.s[i] == '{')) { continue; } - /* extract argument */ - save_char(lexer, ','); /* add ',' to start next argument to `format()` */ - for (; i < buf_unparsed_fstr.len; i++) { - ch = buf_unparsed_fstr.s[i]; - if (ch == '=' || ch == ':' || ch == '}') { break; } - save_char(lexer, ch); /* copy expression until we reach ':', '=' or '}' */ - } - /* no need to check for end of string here, it was done already in first pass */ - if (ch == ':' || ch == '=') { /* if '=' or ':', skip everyting until '}' */ - i++; - for (; i < buf_unparsed_fstr.len; i++) { - ch = buf_unparsed_fstr.s[i]; - if (ch == '}') { break; } - } - } - } - } - save_char(lexer, ')'); /* add final ')' */ - - /* Situation now: */ - /* `buf_unparsed_fstr` contains the buffer of the input unparsed f-string, ex: "age: {age:2i}" */ - /* `lexer->buf` contains the buffer of the transpiled f-string without call to format(), ex: '("age: %2i", age)' */ - /* `reader_save` contains the original reader to continue parsing after f-string */ - /* `lexer->reader` will contain a temporary reader from the parsed f-string */ - - /* extract the parsed f-string from the temporary buffer (needs later deallocation) */ - char * parsed_fstr_s = lexer->buf.s; /* needs later deallocation with parsed_fstr_size */ - size_t parsed_fstr_len = lexer->buf.len; - size_t parsed_fstr_size = lexer->buf.size; - - /* restore buf to lexer */ - lexer->buf = buf_unparsed_fstr; - - /* change the temporary reader to the parsed f-string */ - lexer->reader.len = parsed_fstr_len; - lexer->reader.data = (void*) reader_save; /* link to the saved context */ - lexer->reader.s = parsed_fstr_s; /* reader is responisble to deallocate later this buffer */ - lexer->reader.readf = _bufgets; - - /* add information needed for `_bufgets` to later deallocate the buffer */ - reader_save->size = parsed_fstr_size; - reader_save->s = parsed_fstr_s; - - /* start parsing the parsed f-string, which is btw always '(' */ - next(lexer); - - /* remember that we are still in `scan_identifier()`, we replace the 'f' identifier to 'format' which is the global function to call */ - static const char FORMAT[] = "format"; - lexer->buf.len = sizeof(FORMAT) - 1; /* we now that buf size is at least SHORT_STR_LEN (32) */ - memmove(lexer->buf.s, FORMAT, lexer->buf.len); -} - -static btokentype scan_identifier(blexer *lexer) -{ - int type; - bstring *s; - save(lexer); - match(lexer, is_word); - /* check if the form is f"aaaa" or f'aaa' */ - char ch = lgetc(lexer); - if ((lexer->buf.len == 1) && (lexer->buf.s[0] == 'f') && (ch == '"' || ch == '\'')) { - scan_f_string(lexer); - } - s = buf_tostr(lexer); - type = str_extra(s); - if (type >= KeyIf && type < type_count()) { - lexer->token.type = (btokentype)type; - return lexer->token.type; - } - setstr(lexer, s); /* set identifier name */ - return TokenId; -} - -/* munch any delimeter and return 1 if any found */ -static int skip_delimiter(blexer *lexer) { - int c = lgetc(lexer); - int delimeter_present = 0; - while (1) { - if (c == '#') { - skip_comment(lexer); - } else if (c == '\r' || c == '\n') { - skip_newline(lexer); - } else if (c == ' ' || c == '\t' || c == '\f' || c == '\v') { - next(lexer); - } else { - break; - } - c = lgetc(lexer); - delimeter_present = 1; - } - return delimeter_present; -} - -static btokentype scan_string(blexer *lexer) -{ - while (1) { /* handle multiple string literals in a row */ - int c; - int end = lgetc(lexer); /* string delimiter, either '"' or '\'' */ - next(lexer); /* skip '"' or '\'' */ - while ((c = lgetc(lexer)) != EOS && (c != end)) { - save(lexer); - if (c == '\\') { - save(lexer); /* skip '\\.' */ - } - } - if (c == EOS) { - be_lexerror(lexer, "unfinished string"); - } - c = next(lexer); /* skip '"' or '\'' */ - /* check if there's an additional string literal right after */ - skip_delimiter(lexer); - c = lgetc(lexer); - if (c != '"' && c != '\'') { break; } - } - tr_string(lexer); - setstr(lexer, buf_tostr(lexer)); - return TokenString; -} - -static btokentype scan_assign(blexer *lexer, btokentype is, btokentype not) -{ - next(lexer); - return check_next(lexer, '=') ? is : not; -} - -static btokentype scan_sub(blexer *lexer) -{ - btokentype op; - switch (next(lexer)) { - case '>': op = OptArrow; break; - case '=': op = OptSubAssign; break; - default: return OptSub; - } - next(lexer); - return op; -} - -static btokentype scan_and(blexer *lexer) -{ - btokentype op; - switch (next(lexer)) { - case '&': op = OptAnd; break; - case '=': op = OptAndAssign; break; - default: return OptBitAnd; - } - next(lexer); - return op; -} - -static btokentype scan_or(blexer *lexer) -{ - btokentype op; - switch (next(lexer)) { - case '|': op = OptOr; break; - case '=': op = OptOrAssign; break; - default: return OptBitOr; - } - next(lexer); - return op; -} - -static btokentype scan_le(blexer *lexer) -{ - switch (next(lexer)) { - case '=': - next(lexer); - return OptLE; - case '<': - next(lexer); - return check_next(lexer, '=') ? OptLsfAssign : OptShiftL; - default: - return OptLT; - } -} - -static btokentype scan_ge(blexer *lexer) -{ - switch (next(lexer)) { - case '=': - next(lexer); - return OptGE; - case '>': - next(lexer); - return check_next(lexer, '=') ? OptRsfAssign : OptShiftR; - default: - return OptGT; - } -} - -static btokentype lexer_next(blexer *lexer) -{ - for (;;) { - switch (lgetc(lexer)) { - case '\r': case '\n': /* newline */ - skip_newline(lexer); - break; - case ' ': case '\t': case '\f': case '\v': /* spaces */ - next(lexer); - break; - case '#': /* comment */ - skip_comment(lexer); - break; - case EOS: return TokenEOS; /* end of source stream */ - /* operator */ - case '+': return scan_assign(lexer, OptAddAssign, OptAdd); - case '-': return scan_sub(lexer); - case '*': return scan_assign(lexer, OptMulAssign, OptMul); - case '/': return scan_assign(lexer, OptDivAssign, OptDiv); - case '%': return scan_assign(lexer, OptModAssign, OptMod); - case '(': next(lexer); return OptLBK; - case ')': next(lexer); return OptRBK; - case '[': next(lexer); return OptLSB; - case ']': next(lexer); return OptRSB; - case '{': next(lexer); return OptLBR; - case '}': next(lexer); return OptRBR; - case ',': next(lexer); return OptComma; - case ';': next(lexer); return OptSemic; - case ':': - next(lexer); - return check_next(lexer, '=') ? OptWalrus : OptColon; - case '?': next(lexer); return OptQuestion; - case '^': return scan_assign(lexer, OptXorAssign, OptBitXor); - case '~': next(lexer); return OptFlip; - case '&': return scan_and(lexer); - case '|': return scan_or(lexer); - case '<': return scan_le(lexer); - case '>': return scan_ge(lexer); - case '=': - next(lexer); - return check_next(lexer, '=') ? OptEQ : OptAssign; - case '!': - next(lexer); - return check_next(lexer, '=') ? OptNE : OptNot; - case '\'': case '"': - return scan_string(lexer); - case '.': - return scan_dot_real(lexer); - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return scan_numeral(lexer); - default: - if (is_letter(lgetc(lexer))) { - return scan_identifier(lexer); - } - be_lexerror(lexer, be_pushfstring(lexer->vm, - "stray '\\%d' in program", (unsigned char)lgetc(lexer))); - return TokenNone; /* error */ - } - } -} - -static void lexerbuf_init(blexer *lexer) -{ - lexer->buf.size = SHORT_STR_LEN; - lexer->buf.s = be_malloc(lexer->vm, SHORT_STR_LEN); - lexer->buf.len = 0; -} - -void be_lexer_init(blexer *lexer, bvm *vm, - const char *fname, breader reader, void *data) -{ - lexer->vm = vm; - lexer->cacheType = TokenNone; - lexer->fname = fname; - lexer->linenumber = 1; - lexer->lastline = 1; - lexer->reader.readf = reader; - lexer->reader.data = data; - lexer->reader.len = 0; - lexerbuf_init(lexer); - keyword_registe(vm); - lexer->strtab = be_map_new(vm); - var_setmap(vm->top, lexer->strtab); - be_stackpush(vm); /* save string to cache */ - next(lexer); /* read the first character */ -} - -void be_lexer_deinit(blexer *lexer) -{ - be_free(lexer->vm, lexer->buf.s, lexer->buf.size); - keyword_unregiste(lexer->vm); -} - -int be_lexer_scan_next(blexer *lexer) -{ - btokentype type; - if (lexer->cacheType != TokenNone) { - lexer->token.type = lexer->cacheType; - lexer->cacheType = TokenNone; - return 1; - } - if (lgetc(lexer) == EOS) { /* clear lexer */ - lexer->token.type = TokenEOS; - return 0; - } - lexer->lastline = lexer->linenumber; - type = lexer_next(lexer); - clear_buf(lexer); - if (type != TokenNone) { - lexer->token.type = type; - } else { - lexer->token.type = TokenEOS; - return 0; - } - return 1; -} - -const char* be_token2str(bvm *vm, btoken *token) -{ - switch (token->type) { - case TokenString: - case TokenId: - return str(token->u.s); - case TokenInteger: - return be_pushfstring(vm, "%d", token->u.i); - case TokenReal: - return be_pushfstring(vm, "%g", token->u.r); - default: - return kwords_tab[token->type]; - } -} - -const char* be_tokentype2str(btokentype type) -{ - return kwords_tab[type]; -} - -#endif diff --git a/lib/libesp32/Berry/src/be_lexer.h b/lib/libesp32/Berry/src/be_lexer.h deleted file mode 100644 index e166a1a64f51..000000000000 --- a/lib/libesp32/Berry/src/be_lexer.h +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_LEXER_H -#define BE_LEXER_H - -#include "be_object.h" - -typedef enum { - TokenNone = 0, - TokenEOS, /* end of source */ - TokenId, /* identifier */ - TokenInteger, - TokenReal, - TokenString, - /* operator, don't change order */ - /* assign operator */ - OptAssign, /* operator, = */ - OptAddAssign, /* operator, += */ - OptSubAssign, /* operator, -= */ - OptMulAssign, /* operator, *= */ - OptDivAssign, /* operator, /= */ - OptModAssign, /* operator, %= */ - OptAndAssign, /* operator, &= */ - OptOrAssign, /* operator, |= */ - OptXorAssign, /* operator, ^= */ - OptLsfAssign, /* operator, <<= */ - OptRsfAssign, /* operator, >>= */ - /* binary operator */ - OptAdd, /* operator, + */ - OptSub, /* operator, - */ - OptMul, /* operator, * */ - OptDiv, /* operator, / */ - OptMod, /* operator, % */ - OptLT, /* operator, < */ - OptLE, /* operator, <= */ - OptEQ, /* operator, == */ - OptNE, /* operator, != */ - OptGT, /* operator, > */ - OptGE, /* operator, >= */ - OptBitAnd, /* operatoe, & */ - OptBitOr, /* operatoe, | */ - OptBitXor, /* operatoe, ^ */ - OptShiftL, /* operatoe, << */ - OptShiftR, /* operatoe, >> */ - OptConnect, /* operator, .. */ - OptAnd, /* operator, && */ - OptOr, /* operator, || */ - /* unary operator */ - OptNot, /* operator, ! */ - OptFlip, /* operator, ~ */ - /* postfix operator or bracket */ - OptLBK, /* operator, ( bracket */ - OptRBK, /* operator, ) bracket */ - OptLSB, /* operator, [ square bracket */ - OptRSB, /* operator, ] square bracket */ - OptLBR, /* operator, { brace */ - OptRBR, /* operator, } brace */ - OptDot, /* operator, . dot */ - /* other symbol */ - OptComma, /* operator, , */ - OptSemic, /* operator, ; */ - OptColon, /* operator, : */ - OptQuestion, /* operator, ? */ - OptArrow, /* operator, -> */ - /* keyword */ - KeyIf, /* keyword if */ - KeyElif, /* keyword elif */ - KeyElse, /* keyword else */ - KeyWhile, /* keyword while */ - KeyFor, /* keyword for */ - KeyDef, /* keyword def */ - KeyEnd, /* keyword end */ - KeyClass, /* keyword class */ - KeyBreak, /* keyword break */ - KeyContinue, /* keyword continue */ - KeyReturn, /* keyword return */ - KeyTrue, /* keyword true */ - KeyFalse, /* keyword false */ - KeyNil, /* keyword nil */ - KeyVar, /* keyword var */ - KeyDo, /* keyword do */ - KeyImport, /* keyword import */ - KeyAs, /* keyword as */ - KeyTry, /* keyword try */ - KeyExcept, /* keyword except */ - KeyRaise, /* keyword raise */ - KeyStatic, /* keyword static */ - /* Walrus operator */ - OptWalrus, /* operator, := */ -} btokentype; - -struct blexerreader { - const char *s; - size_t len; - void *data; - breader readf; - int cursor; -}; - -struct blexerbuf { - char *s; - size_t len, size; -}; - -typedef struct btoken { - btokentype type; - union { - bstring *s; - bint i; - breal r; - } u; -} btoken; - -typedef struct blexer { - const char *fname; - btoken token; - int linenumber; - int lastline; - btokentype cacheType; - struct blexerbuf buf; - struct blexerreader reader; - bmap *strtab; - bvm *vm; -} blexer; - -void be_lexer_init(blexer *lexer, bvm *vm, - const char *fname, breader reader, void *data); -void be_lexer_deinit(blexer *lexer); -void be_lexerror(blexer *lexer, const char *msg); -int be_lexer_scan_next(blexer *lexer); -bstring* be_lexer_newstr(blexer *lexer, const char *str); -const char *be_token2str(bvm *vm, btoken *token); -const char* be_tokentype2str(btokentype type); - -#endif diff --git a/lib/libesp32/Berry/src/be_libs.c b/lib/libesp32/Berry/src/be_libs.c deleted file mode 100644 index a9a2f0e39909..000000000000 --- a/lib/libesp32/Berry/src/be_libs.c +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_libs.h" - -extern void be_load_baselib(bvm *vm); -extern void be_load_baselib_next(bvm *vm); -extern void be_load_listlib(bvm *vm); -extern void be_load_maplib(bvm *vm); -extern void be_load_rangelib(bvm *vm); -extern void be_load_filelib(bvm *vm); -extern void be_load_byteslib(bvm *vm); - -void be_loadlibs(bvm *vm) -{ - be_load_baselib(vm); -#if !BE_USE_PRECOMPILED_OBJECT - be_load_listlib(vm); - be_load_maplib(vm); - be_load_rangelib(vm); - be_load_filelib(vm); - be_load_byteslib(vm); - be_load_baselib_next(vm); -#endif -} diff --git a/lib/libesp32/Berry/src/be_libs.h b/lib/libesp32/Berry/src/be_libs.h deleted file mode 100644 index a8014790bbfe..000000000000 --- a/lib/libesp32/Berry/src/be_libs.h +++ /dev/null @@ -1,15 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_LIBS_H -#define BE_LIBS_H - -#include "berry.h" - -void be_loadlibs(bvm *vm); - -#endif diff --git a/lib/libesp32/Berry/src/be_list.c b/lib/libesp32/Berry/src/be_list.c deleted file mode 100644 index 7d696d736aee..000000000000 --- a/lib/libesp32/Berry/src/be_list.c +++ /dev/null @@ -1,207 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_list.h" -#include "be_mem.h" -#include "be_gc.h" -#include "be_vm.h" -#include "be_vector.h" -#include "be_exec.h" -#include - -#define datasize(size) ((size) * sizeof(bvalue)) - -blist* be_list_new(bvm *vm) -{ - bgcobject *gco = be_gcnew(vm, BE_LIST, blist); - blist *list = cast_list(gco); - if (list) { - list->count = 0; - list->capacity = 2; - var_setlist(vm->top, list); - be_incrtop(vm); - list->data = be_malloc(vm, datasize(list->capacity)); - be_stackpop(vm, 1); - } - return list; -} - -void be_list_delete(bvm *vm, blist *list) -{ - be_free(vm, list->data, datasize(list->capacity)); - be_free(vm, list, sizeof(blist)); -} - -blist* be_list_copy(bvm *vm, blist *original) -{ - bgcobject *gco = be_gcnew(vm, BE_LIST, blist); - blist *list = cast_list(gco); - if (list) { - size_t size = datasize(original->capacity); - list->count = original->count; - list->capacity = original->capacity; - var_setlist(vm->top, list); - be_incrtop(vm); - list->data = be_malloc(vm, size); - be_stackpop(vm, 1); - memcpy(list->data, original->data, size); - } - return list; -} - -bvalue* be_list_index(blist *list, int index) -{ - if (index < 0) { - index = list->count + index; - } - if (index < 0 || index >= list->count) { - return NULL; - } - return be_list_at(list, index); -} - -bvalue* be_list_push(bvm *vm, blist *list, bvalue *value) -{ - bvalue *slot; - if (list->count >= list->capacity) { - int newcap = be_nextsize(list->capacity); - list->data = be_realloc(vm, list->data, - datasize(list->capacity), datasize(newcap)); - list->capacity = newcap; - } - slot = list->data + list->count++; - if (value != NULL) { - *slot = *value; - } - return slot; -} - -bvalue* be_list_insert(bvm *vm, blist *list, int index, bvalue *value) -{ - int i; - bvalue *data; - if (index < 0) { - index = list->count + index; - } - if (index < 0 || index > list->count) { - return NULL; - } - if (list->count >= list->capacity) { - int newcap = be_nextsize(list->capacity); - list->data = be_realloc(vm, list->data, - datasize(list->capacity), datasize(newcap)); - list->capacity = newcap; - } - data = list->data; - for (i = list->count++; i > index; --i) { - data[i] = data[i - 1]; - } - data = list->data + index; - if (value != NULL) { - *data = *value; - } - return data; -} - -int be_list_remove(bvm *vm, blist *list, int index) -{ - int i; - bvalue *data; - (void)vm; - if (index < 0) { - index = list->count + index; - } - if (index < 0 || index >= list->count) { - return bfalse; - } - data = list->data; - list->count--; - for (i = index; i < list->count; ++i) { - data[i] = data[i + 1]; - } - return btrue; -} - -void be_list_resize(bvm *vm, blist *list, int count) -{ - if (count != list->count) { - int newcap = be_nextsize(count); - if (newcap > list->capacity) { - bvalue *v, *end; - list->data = be_realloc(vm, list->data, - datasize(list->capacity), datasize(newcap)); - list->capacity = newcap; - v = list->data + list->count; - end = list->data + count; - while (v < end) { - var_setnil(v++); - } - } - list->count = count; - } -} - -void be_list_merge(bvm *vm, blist *list, const blist *other) -{ - int dst_len = list->count; - int src_len = other->count; - int length = src_len + dst_len; - if (length != 0) { - int newcap = be_nextsize(length); - if (newcap > list->capacity) { - list->data = be_realloc(vm, list->data, - datasize(list->capacity), datasize(newcap)); - list->capacity = newcap; - } - memcpy(list->data + dst_len, other->data, src_len * sizeof(bvalue)); - list->count = length; - } -} - -void be_list_reverse(blist *list) -{ - bvalue *left = list->data; - bvalue *right = left + list->count - 1; - for (; left < right; ++left, --right) { - bvalue temp = *left; - *left = *right; - *right = temp; - } -} - -void be_list_pool_init(bvm *vm, blist *list) -{ - bvalue *head; - be_list_resize(vm, list, 0); - head = be_list_push(vm, list, NULL); - var_setint(head, 0); -} - -int be_list_pool_alloc(bvm *vm, blist *list, bvalue *src) -{ - bvalue *head = be_list_data(list), *node; - int id = var_toidx(head); /* get the first free node */ - if (id) { - node = head + id; - head->v.i = var_toint(node); /* link the next free node to head */ - } else { - id = be_list_count(list); - node = be_list_push(vm, list, NULL); - } - *node = *src; - return id; -} - -void be_list_pool_free(blist *list, int id) -{ - bvalue *head = be_list_data(list); - bvalue *node = head + id; - be_assert(id > 0 && id < list->count); - /* insert a new free node to head */ - *node = *head; - head->v.i = id; -} diff --git a/lib/libesp32/Berry/src/be_list.h b/lib/libesp32/Berry/src/be_list.h deleted file mode 100644 index 9f574572586f..000000000000 --- a/lib/libesp32/Berry/src/be_list.h +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_LIST_H -#define BE_LIST_H - -#include "be_object.h" - -struct blist { - bcommon_header; - bgcobject *gray; /* for gc gray list */ - int count, capacity; - bvalue *data; -}; - -#define be_list_data(list) ((list)->data) -#define be_list_count(list) ((list)->count) -#define be_list_at(list, index) ((list)->data + index) -#define be_list_end(list) ((list)->data + (list)->count) - -blist* be_list_new(bvm *vm); -void be_list_delete(bvm *vm, blist *list); -blist* be_list_copy(bvm *vm, blist *original); -bvalue* be_list_index(blist *list, int index); -bvalue* be_list_push(bvm *vm, blist *list, bvalue *value); -bvalue* be_list_insert(bvm *vm, blist *list, int index, bvalue *value); -int be_list_remove(bvm *vm, blist *list, int index); -void be_list_resize(bvm *vm, blist *list, int count); -void be_list_merge(bvm *vm, blist *list, const blist *other); -void be_list_reverse(blist *list); -void be_list_pool_init(bvm *vm, blist *list); -int be_list_pool_alloc(bvm *vm, blist *list, bvalue *src); -void be_list_pool_free(blist *list, int id); - -#endif diff --git a/lib/libesp32/Berry/src/be_listlib.c b/lib/libesp32/Berry/src/be_listlib.c deleted file mode 100644 index 9cbfa38b0994..000000000000 --- a/lib/libesp32/Berry/src/be_listlib.c +++ /dev/null @@ -1,556 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_string.h" -#include "be_strlib.h" -#include "be_list.h" -#include "be_func.h" -#include "be_exec.h" -#include "be_vm.h" -#include - -#define list_check_data(vm, argc) \ - if (!be_islist(vm, -1) || be_top(vm) - 1 < argc) { \ - be_return_nil(vm); \ - } - -#define list_check_ref(vm) \ - if (be_refcontains(vm, 1)) { \ - be_pushstring(vm, "[...]"); \ - be_return(vm); \ - } - -static void list_getindex(bvm *vm, int index) -{ - if (!be_getindex(vm, index)) { - be_raise(vm, "index_error", "list index out of range"); - } -} - -static int m_init(bvm *vm) -{ - int i, argc = be_top(vm); - if (argc > 1 && be_islist(vm, 2)) { - be_pushvalue(vm, 2); - be_setmember(vm, 1, ".p"); - } else { - be_newlist(vm); - be_setmember(vm, 1, ".p"); - for (i = 2; i <= argc; ++i) { - be_pushvalue(vm, i); - be_data_push(vm, -2); - be_pop(vm, 1); - } - } - be_return_nil(vm); -} - -static void push_element(bvm *vm) -{ - be_toescape(vm, -1, 'x'); /* escape string */ - be_strconcat(vm, -3); - be_pop(vm, 1); -} - -static int m_tostring(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - list_check_ref(vm); - be_refpush(vm, 1); - be_pushstring(vm, "["); - be_pushiter(vm, -2); - while (be_iter_hasnext(vm, -3)) { - be_iter_next(vm, -3); - push_element(vm); - if (be_iter_hasnext(vm, -3)) { - be_pushstring(vm, ", "); - be_strconcat(vm, -3); - be_pop(vm, 1); - } - } - be_pop(vm, 1); /* pop iterator */ - be_pushstring(vm, "]"); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_refpop(vm); - be_return(vm); -} - -static int m_push(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 2); - be_pushvalue(vm, 2); - be_data_push(vm, -2); - be_return_nil(vm); -} - -static int m_pop(bvm *vm) -{ - int argc = be_top(vm); - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - if (argc >= 2) { - be_pushvalue(vm, 2); - } else { - be_pushint(vm, -1); - } - list_getindex(vm, -2); - be_pushvalue(vm, -2); - be_data_remove(vm, -4); - be_pop(vm, 1); - be_return(vm); -} - -static int m_insert(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 3); - be_pushvalue(vm, 2); - be_pushvalue(vm, 3); - be_data_insert(vm, -3); - be_return_nil(vm); -} - -static int m_remove(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 2); - be_pushvalue(vm, 2); - be_data_remove(vm, -2); - be_return_nil(vm); -} - -static int item_range(bvm *vm) -{ - bint lower, upper; - bint size = be_data_size(vm, -1); /* get source list size */ - /* get index range */ - be_getmember(vm, 2, "__lower__"); - lower = be_toint(vm, -1); - if (lower < 0) { - lower = size + lower; - } - be_pop(vm, 1); - be_getmember(vm, 2, "__upper__"); - upper = be_toint(vm, -1); - if (upper < 0) { - upper = size + upper; - } - be_pop(vm, 1); - /* protection scope */ - upper = upper < size ? upper : size - 1; - lower = lower < 0 ? 0 : lower; - /* construction result list instance */ - be_newobject(vm, "list"); /* result list */ - be_getmember(vm, 1, ".p"); /* source list */ - /* copy elements */ - for (; lower <= upper; ++lower) { - be_pushint(vm, lower); - list_getindex(vm, -2); - be_data_push(vm, -4); - be_pop(vm, 2); - } - be_pop(vm, 2); - be_return(vm); -} - -static int item_list(bvm *vm) -{ - int i, srcsize, idxsize; - be_getmember(vm, 2, ".p"); /* get index list */ - srcsize = be_data_size(vm, -2); /* get source list size */ - idxsize = be_data_size(vm, -1); /* get index list size */ - /* construction result list instance */ - be_newobject(vm, "list"); /* result list */ - be_getmember(vm, 1, ".p"); /* source list */ - /* copy elements */ - for (i = 0; i < idxsize; ++i) { - be_pushint(vm, i); - be_getindex(vm, -5); - if (be_isint(vm, -1)) { - int idx = be_toindex(vm, -1); - if (idx >= 0 && idx < srcsize) { - be_getindex(vm, -3); - } else { - be_pushnil(vm); - } - } else { - be_pushnil(vm); - } - be_data_push(vm, -5); - be_pop(vm, 3); - } - be_pop(vm, 2); - be_return(vm); -} - -static int m_item(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 2); - if (be_isint(vm, 2)) { - be_pushvalue(vm, 2); - list_getindex(vm, -2); - be_return(vm); - } - if (be_isinstance(vm, 2)) { - const char *cname = be_classname(vm, 2); - if (!strcmp(cname, "range")) { - return item_range(vm); - } - if (!strcmp(cname, "list")) { - return item_list(vm); - } - } - be_raise(vm, "index_error", "list index out of range"); - be_return_nil(vm); -} - -static int m_find(bvm *vm) -{ - bbool found = bfalse; - int idx; - be_getmember(vm, 1, ".p"); - list_check_data(vm, 2); - list_check_ref(vm); - be_refpush(vm, 1); - be_pushiter(vm, -1); - for (idx=0; be_iter_hasnext(vm, -2); idx++) { - be_iter_next(vm, -2); - be_pushvalue(vm, 2); /* push needle to compare */ - if (be_iseq(vm)) { - found = btrue; - be_pop(vm, 2); - break; - } - be_pop(vm, 2); - } - be_pop(vm, 1); /* pop iterator */ - be_refpop(vm); - if (found) { - be_pushint(vm, idx); - be_return(vm); - } else { - be_return_nil(vm); - } -} - -static int m_setitem(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 3); - be_pushvalue(vm, 2); - be_pushvalue(vm, 3); - if (!be_setindex(vm, -3)) { - be_raise(vm, "index_error", "list assignment index out of range"); - } - be_return_nil(vm); -} - -static int m_size(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - be_pushint(vm, be_data_size(vm, -1)); - be_return(vm); -} - -static int m_tobool(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - be_pushbool(vm, be_data_size(vm, -1) > 0); - be_return(vm); -} - -static int m_resize(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 2); - be_pushvalue(vm, 2); - be_data_resize(vm, -2); - be_return_nil(vm); -} - -static int m_clear(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - be_pushint(vm, 0); - be_data_resize(vm, -2); - be_return_nil(vm); -} - -static int iter_closure(bvm *vm) -{ - /* for better performance, we operate the upvalues - * directly without using by the stack. */ - bntvclos *func = var_toobj(vm->cf->func); - bvalue *uv0 = be_ntvclos_upval(func, 0)->value; /* list value */ - bvalue *uv1 = be_ntvclos_upval(func, 1)->value; /* iter value */ - bvalue *next = cast(bvalue*, var_toobj(uv1)) + 1; - blist *list = var_toobj(uv0); - if (next >= be_list_end(list)) { - be_stop_iteration(vm); - } - var_toobj(uv1) = next; /* set upvale[1] (iter value) */ - /* push next value to top */ - var_setval(vm->top, next); - be_incrtop(vm); - be_return(vm); -} - -static int m_iter(bvm *vm) -{ - be_pushntvclosure(vm, iter_closure, 2); - be_getmember(vm, 1, ".p"); - be_setupval(vm, -2, 0); - be_pushiter(vm, -1); - be_setupval(vm, -3, 1); - be_pop(vm, 2); - be_return(vm); -} - -static int m_connect(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 2) { - be_getmember(vm, 1, ".p"); - be_pushvalue(vm, 2); - be_data_push(vm, -2); - be_pop(vm, argc + 1); - } - be_return(vm); /* return self */ -} - -static int m_merge(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 2) { - be_newobject(vm, "list"); /* stack contains instance and .p */ - be_getmember(vm, 1, ".p"); - be_data_merge(vm, -2); - be_getmember(vm, 2, ".p"); - if (!be_islist(vm, -1)) { - be_raise(vm, "type_error", "operand must be a list"); - } - be_data_merge(vm, -3); - be_pop(vm, 3); - } - be_return(vm); /* return self */ -} - -static void connect(bvm *vm, bvalue *begin, bvalue *end, const char * delimiter, bbool first_element) -{ - size_t l0 = be_strlen(vm, -1), len = l0; - size_t d = delimiter ? strlen(delimiter) : 0; /* len of delimiter */ - char *buf, *p; - bvalue *it; - for (it = begin; it < end; ++it) { - len += str_len(var_tostr(it)) + d; - } - if (first_element) { - len -= d; /* remove size for first delimiter non needed */ - } - buf = be_pushbuffer(vm, len); - memcpy(buf, be_tostring(vm, -2), l0); - p = buf + l0; - for (it = begin; it < end; ++it) { - if ((it != begin || !first_element) && delimiter) { - /* add delimiter */ - memcpy(p, delimiter, d); - p += d; - } - bstring *s = var_tostr(it); - size_t l = str_len(s); - memcpy(p, str(s), l); - p += l; - } - be_pushstring(vm, buf); - be_moveto(vm, -1, -3); - be_pop(vm, 2); -} - -static void list_concat(bvm *vm, blist *list, const char * delimiter) -{ - bvalue *it, *begin = be_list_data(list); - bvalue *end = be_list_end(list); - be_pushstring(vm, ""); /* push a empty string */ - bbool first_element = btrue; - for (it = begin; it < end;) { - for (; it < end && var_isstr(it); ++it); - if (begin < it) { - connect(vm, begin, it, delimiter, first_element); /* connect string list */ - first_element = bfalse; - } - if (it < end) { - if (delimiter && !first_element) { - be_pushstring(vm, delimiter); - be_strconcat(vm, -2); - be_pop(vm, 1); - } - /* connect other value */ - var_setval(vm->top, it); - be_incrtop(vm); - be_val2str(vm, -1); - be_strconcat(vm, -2); - be_pop(vm, 1); - begin = ++it; - first_element = bfalse; - } - } -} - -static int m_concat(bvm *vm) -{ - bvalue *value; - int top = be_top(vm); - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - value = be_indexof(vm, -1); - const char * delimiter = NULL; - if (top >= 2) { - delimiter = be_tostring(vm, 2); - } - list_concat(vm, var_toobj(value), delimiter); - be_return(vm); -} - -static int m_reverse(bvm *vm) -{ - int top = be_top(vm); - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - be_data_reverse(vm, -1); - be_pop(vm, top); - be_return(vm); -} - -static int m_copy(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - be_getbuiltin(vm, "list"); - be_copy(vm, -2); - be_call(vm, 1); - be_pop(vm, 1); - be_return(vm); -} - -static int list_equal(bvm *vm, bbool iseq) -{ - int i, j, res; - bbool (*eqfunc)(bvm*) = iseq ? be_iseq : be_isneq; - be_getmember(vm, 1, ".p"); - be_getmember(vm, 2, ".p"); - i = be_data_size(vm, -2); - j = be_data_size(vm, -1); - if (i == j) { - res = iseq; - for (i = 0; res == iseq && i < j; ++i) { - be_pushint(vm, i); - be_getindex(vm, -3); - be_pushint(vm, i); - be_getindex(vm, -4); - be_remove(vm, -2); - res = eqfunc(vm); - be_pop(vm, 3); - } - } else { - res = !iseq; - } - be_pushbool(vm, res); - be_return(vm); -} - -static int m_keys(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - list_check_data(vm, 1); - int size = be_data_size(vm, -1); - be_getbuiltin(vm, "range"); - be_pushint(vm, 0); - be_pushint(vm, size - 1); - be_call(vm, 2); - be_pop(vm, 2); - be_return(vm); -} - -static int m_equal(bvm *vm) -{ - return list_equal(vm, btrue); -} - -static int m_nequal(bvm *vm) -{ - return list_equal(vm, bfalse); -} - -#if !BE_USE_PRECOMPILED_OBJECT -void be_load_listlib(bvm *vm) -{ - static const bnfuncinfo members[] = { - { ".p", NULL }, - { "init", m_init }, - { "tostring", m_tostring }, - { "push", m_push }, - { "pop", m_pop }, - { "insert", m_insert }, - { "remove", m_remove }, - { "item", m_item }, - { "find", m_find }, - { "setitem", m_setitem }, - { "size", m_size }, - { "resize", m_resize }, - { "clear", m_clear }, - { "iter", m_iter }, - { "concat", m_concat }, - { "reverse", m_reverse }, - { "copy", m_copy }, - { "keys", m_keys }, - { "tobool", m_tobool } - { "..", m_connect }, - { "+", m_merge }, - { "==", m_equal }, - { "!=", m_nequal }, - { NULL, NULL } - }; - be_regclass(vm, "list", members); -} -#else -/* @const_object_info_begin -class be_class_list (scope: global, name: list) { - .p, var - init, func(m_init) - tostring, func(m_tostring) - push, func(m_push) - pop, func(m_pop) - insert, func(m_insert) - remove, func(m_remove) - item, func(m_item) - find, func(m_find) - setitem, func(m_setitem) - size, func(m_size) - resize, func(m_resize) - clear, func(m_clear) - iter, func(m_iter) - concat, func(m_concat) - reverse, func(m_reverse) - copy, func(m_copy) - keys, func(m_keys) - tobool, func(m_tobool) - .., func(m_connect) - +, func(m_merge) - ==, func(m_equal) - !=, func(m_nequal) -} -@const_object_info_end */ -#include "../generate/be_fixed_be_class_list.h" -#endif diff --git a/lib/libesp32/Berry/src/be_map.c b/lib/libesp32/Berry/src/be_map.c deleted file mode 100644 index ea3b81c6f157..000000000000 --- a/lib/libesp32/Berry/src/be_map.c +++ /dev/null @@ -1,354 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_map.h" -#include "be_string.h" -#include "be_vector.h" -#include "be_class.h" -#include "be_mem.h" -#include "be_gc.h" -#include "be_vm.h" -#include "be_exec.h" -#include - -#define key(node) (&(node)->key) -#define value(node) (&(node)->value) -#define isnil(node) var_isnil(key(node)) -#define setnil(node) var_setnil(key(node)) -#define hash2slot(m, h) ((m)->slots + (h) % (m)->size) -#define hashcode(_v) _hashcode(vm, (_v)->type, (_v)->v) -#define keytype(key) ((signed char)(key)->type) - -#define next(node) ((node)->key.next) -#define pos2slot(map, n) ((n) != LASTNODE ? ((map)->slots + (n)) : NULL) -#define pos(map, node) ((int)((node) - (map)->slots)) -#define setkey(node, _v) { (node)->key.type = (bbyte)(_v)->type; \ - (node)->key.v = (_v)->v; } - -#define datasize(size) ((size) * sizeof(bmapnode)) - -#define LASTNODE ((1 << 24) - 1) - -static int map_nextsize(int size) -{ - be_assert(size < LASTNODE); - if (size < LASTNODE) { - return be_nextsize(size); - } - return LASTNODE + 1; -} - -static uint32_t hashptr(void *p) -{ - uintptr_t i = (uintptr_t)p; - return (uint32_t)((i ^ (i >> 16)) & 0xFFFFFFFF); -} - -#if BE_USE_SINGLE_FLOAT -#define hashreal(v) ((uint32_t)((v).i)) -#else -static uint32_t hashreal(union bvaldata v) -{ - union { breal r; uint32_t i[2]; } u; - u.r = v.r; - return u.i[0] ^ u.i[1]; -} -#endif - -#if BE_USE_OVERLOAD_HASH -static uint32_t hashins(bvm *vm, binstance *obj) -{ - int type = be_instance_member(vm, obj, str_literal(vm, "hash"), vm->top); - if (basetype(type) == BE_FUNCTION) { - bvalue *top = vm->top; - var_setinstance(top + 1, obj); - vm->top += 2; - be_dofunc(vm, top, 1); /* call method 'item' */ - vm->top -= 2; - if (!var_isint(vm->top)) { /* check the return value */ - const char *name = str(be_instance_name(obj)); - be_raise(vm, "runtime_error", be_pushfstring(vm, - "the value of `%s::hash()` is not a 'int'", - strlen(name) ? name : "")); - } - return (uint32_t)var_toint(vm->top); - } - return hashptr(obj); -} -#endif - -static uint32_t _hashcode(bvm *vm, int type, union bvaldata v) -{ - (void)vm; - switch (type) { - case BE_NIL: return 0; - case BE_BOOL: return (uint32_t)v.b; - case BE_INT: return (uint32_t)v.i; - case BE_REAL: return hashreal(v); - case BE_STRING: return be_strhash(v.s); -#if BE_USE_OVERLOAD_HASH - case BE_INSTANCE: return hashins(vm, v.p); -#endif - default: return hashptr(v.p); - } -} - -static int eqnode(bvm *vm, bmapnode *node, bvalue *key, uint32_t hash) -{ - (void)vm; - if (!var_isnil(key)) { - bmapkey *k = key(node); -#if BE_USE_OVERLOAD_HASH - if (var_isinstance(key)) { - bvalue kv; - kv.type = k->type; - kv.v = k->v; - return be_vm_iseq(vm, key, &kv); - } -#endif - if(keytype(k) == key->type && hashcode(k) == hash) { - switch (key->type) { - case BE_BOOL: return var_tobool(key) == var_tobool(k); - case BE_INT: return var_toint(key) == var_toint(k); - case BE_REAL: return var_toreal(key) == var_toreal(k); - case BE_STRING: return be_eqstr(var_tostr(key), var_tostr(k)); - default: return var_toobj(key) == var_toobj(k); - } - } - } - return 0; -} - -static bmapnode* findprev(bmap *map, bmapnode *list, bmapnode *slot) -{ - int n, pos = pos(map, slot); - bmapnode *prev = list; - for (;;) { - n = next(prev); - if (n == pos || n == LASTNODE) { - break; - } - prev = map->slots + n; - } - return n == pos ? prev : NULL; -} - -static bmapnode* nextfree(bmap *map) -{ - bmapnode *base = map->slots; - while (map->lastfree >= base) { - if (isnil(map->lastfree)) { - return map->lastfree; - } - --map->lastfree; - } - return NULL; -} - -static bmapnode* insert(bvm *vm, bmap *map, bvalue *key, uint32_t hash) -{ - bmapnode *slot = hash2slot(map, hash); - if (isnil(slot)) { /* empty slot */ - setkey(slot, key); - next(slot) = LASTNODE; - } else { - uint32_t h = hashcode(key(slot)); /* get the hashcode of the exist node */ - bmapnode *mainslot = hash2slot(map, h); /* get the main-slot */ - bmapnode *new = nextfree(map); /* get a free slot */ - if (mainslot == slot) { /* old is main slot */ - /* insert in first */ - setkey(new, key); - next(new) = next(slot); - next(slot) = pos(map, new); - slot = new; - } else { - bmapnode *prev = findprev(map, mainslot, slot); - next(prev) = pos(map, new); /* link the previous node */ - *new = *slot; /* copy to new slot */ - setkey(slot, key); - next(slot) = LASTNODE; - } - } - return slot; -} - -static bmapnode* find(bvm *vm, bmap *map, bvalue *key, uint32_t hash) -{ - bmapnode *slot = hash2slot(map, hash); - if (isnil(slot)) { - return NULL; - } - while (!eqnode(vm, slot, key, hash)) { - int n = next(slot); - if (n == LASTNODE) { - return NULL; - } - slot = map->slots + n; - } - return slot; -} - -static void resize(bvm *vm, bmap *map, int size) -{ - int i, oldsize; - bmapnode *slots, *oldslots; - if (size < map->count) { - return; - } - oldsize = map->size; - oldslots = map->slots; - slots = be_malloc(vm, datasize(size)); - for (i = 0; i < size; ++i) { - setnil(slots + i); - next(slots + i) = LASTNODE; - } - map->size = size; - map->slots = slots; - map->lastfree = slots + size - 1; - /* rehash */ - for (i = 0; i < oldsize; ++i) { - bmapnode *node = oldslots + i; - if (!isnil(node)) { - bvalue v; - bmapnode *newslot; - v.type = node->key.type; - v.v = node->key.v; - newslot = insert(vm, map, &v, hashcode(&v)); - newslot->value = node->value; - } - } - be_free(vm, oldslots, datasize(oldsize)); -} - -bmap* be_map_new(bvm *vm) -{ - bgcobject *gco = be_gcnew(vm, BE_MAP, bmap); - bmap *map = cast_map(gco); - if (map) { - map->size = 0; - map->count = 0; - map->slots = NULL; - var_setmap(vm->top, map); - be_incrtop(vm); - resize(vm, map, 2); - be_stackpop(vm, 1); - } - return map; -} - -void be_map_delete(bvm *vm, bmap *map) -{ - be_free(vm, map->slots, datasize(map->size)); - be_free(vm, map, sizeof(bmap)); -} - -bvalue* be_map_find(bvm *vm, bmap *map, bvalue *key) -{ - bmapnode *entry = find(vm, map, key, hashcode(key)); - return entry ? value(entry) : NULL; -} - -bvalue* be_map_insert(bvm *vm, bmap *map, bvalue *key, bvalue *value) -{ - uint32_t hash = hashcode(key); - bmapnode *entry = find(vm, map, key, hash); - if (!entry) { /* new entry */ - if (map->count >= map->size) { - resize(vm, map, map_nextsize(map->size)); - } - entry = insert(vm, map, key, hash); - ++map->count; - } - if (value) { - entry->value = *value; - } - return value(entry); -} - -int be_map_remove(bvm *vm, bmap *map, bvalue *key) -{ - uint32_t hash = hashcode(key); - bmapnode *slot = hash2slot(map, hash); /* main slot */ - - if (eqnode(vm, slot, key, hash)) { /* first node */ - bmapnode *next = pos2slot(map, next(slot)); - if (next) { /* has next */ - *slot = *next; /* first: copy the second node to the slot */ - slot = next; /* second: set the second node to nil (empty) */ - } - } else { /* the node will be remove is not first-node */ - bmapnode *prev = slot; - for (;;) { /* find the previous node */ - int n = next(prev); - slot = pos2slot(map, n); - if (slot == NULL) { /* node not found */ - return bfalse; - } - if (eqnode(vm, slot, key, hash)) { - break; - } - prev = slot; - } - /* link the list */ - next(prev) = next(slot); - } - /* set to nil */ - setnil(slot); - /* add to lastfree */ - if (map->lastfree < slot) { - map->lastfree = slot; - } - --map->count; - return btrue; -} - -bvalue* be_map_findstr(bvm *vm, bmap *map, bstring *key) -{ - bvalue v; - var_setstr(&v, key); - return be_map_find(vm, map, &v); -} - -bvalue* be_map_insertstr(bvm *vm, bmap *map, bstring *key, bvalue *value) -{ - bvalue v; - var_setstr(&v, key); - set_fixed(key); - bvalue * r = be_map_insert(vm, map, &v, value); - restore_fixed(key); - return r; -} - -void be_map_removestr(bvm *vm, bmap *map, bstring *key) -{ - bvalue v; - var_setstr(&v, key); - be_map_remove(vm, map, &v); -} - -bmapnode* be_map_next(bmap *map, bmapiter *iter) -{ - bmapnode *end = map->slots + map->size; - *iter = *iter ? *iter + 1 : map->slots; - while (*iter < end && isnil(*iter)) { - ++(*iter); - } - return *iter < end ? *iter : NULL; -} - -bmapnode* be_map_val2node(bvalue *value) -{ - return (bmapnode *)((size_t)value - sizeof(bmapkey)); -} - -void be_map_compact(bvm *vm, bmap *map) -{ - (void)vm; - if (!gc_isconst(map)) { - resize(vm, map, map->count ? map->count : 1); - } -} diff --git a/lib/libesp32/Berry/src/be_map.h b/lib/libesp32/Berry/src/be_map.h deleted file mode 100644 index 7ae76962c940..000000000000 --- a/lib/libesp32/Berry/src/be_map.h +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_MAP_H -#define BE_MAP_H - -#include "be_object.h" - -typedef struct bmapkey { - union bvaldata v; - uint32_t type:8; - uint32_t next:24; -} bmapkey; - -typedef struct bmapnode { - bmapkey key; - bvalue value; -} bmapnode; - -struct bmap { - bcommon_header; - bgcobject *gray; /* for gc gray list */ - bmapnode *slots; - bmapnode *lastfree; - int size; - int count; -#ifdef __cplusplus - BE_CONSTEXPR bmap(bmapnode *s, int n) : - next(0), type(BE_MAP), marked(GC_CONST), gray(0), - slots(s), lastfree(0), size(n), count(n) {} -#endif -}; - -typedef bmapnode *bmapiter; - -#define be_map_iter() NULL -#define be_map_count(map) ((map)->count) -#define be_map_size(map) (map->size) - -#define be_map_key2value(dst, node) do { \ - (dst)->type = (node)->key.type; \ - (dst)->v = (node)->key.v; \ -} while (0); - -bmap* be_map_new(bvm *vm); -void be_map_delete(bvm *vm, bmap *map); -bvalue* be_map_find(bvm *vm, bmap *map, bvalue *key); -bvalue* be_map_insert(bvm *vm, bmap *map, bvalue *key, bvalue *value); -int be_map_remove(bvm *vm, bmap *map, bvalue *key); -bvalue* be_map_findstr(bvm *vm, bmap *map, bstring *key); -bvalue* be_map_insertstr(bvm *vm, bmap *map, bstring *key, bvalue *value); -void be_map_removestr(bvm *vm, bmap *map, bstring *key); -bmapnode* be_map_next(bmap *map, bmapiter *iter); -bmapnode* be_map_val2node(bvalue *value); -void be_map_compact(bvm *vm, bmap *map); - -#endif diff --git a/lib/libesp32/Berry/src/be_maplib.c b/lib/libesp32/Berry/src/be_maplib.c deleted file mode 100644 index bf05f1a2934b..000000000000 --- a/lib/libesp32/Berry/src/be_maplib.c +++ /dev/null @@ -1,265 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_func.h" -#include "be_exec.h" -#include "be_map.h" -#include "be_vm.h" - -#define map_check_data(vm, argc) \ - if (!be_ismap(vm, -1) || be_top(vm) - 1 < argc) { \ - be_return_nil(vm); \ - } - -#define map_check_ref(vm) \ - if (be_refcontains(vm, 1)) { \ - be_pushstring(vm, "{...}"); \ - be_return(vm); \ - } - -static int m_init(bvm *vm) -{ - if (be_top(vm) > 1 && be_ismap(vm, 2)) { - be_pushvalue(vm, 2); - be_setmember(vm, 1, ".p"); - } else { - be_newmap(vm); - be_setmember(vm, 1, ".p"); - } - be_return_nil(vm); -} - -static void push_key(bvm *vm) -{ - be_toescape(vm, -2, 'x'); /* escape string */ - be_pushvalue(vm, -2); /* push to top */ - be_strconcat(vm, -5); - be_pop(vm, 1); -} - -static void push_value(bvm *vm) -{ - be_toescape(vm, -1, 'x'); /* escape string */ - be_strconcat(vm, -4); - be_pop(vm, 2); - if (be_iter_hasnext(vm, -3)) { - be_pushstring(vm, ", "); - be_strconcat(vm, -3); - be_pop(vm, 1); - } -} - -static int m_tostring(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - map_check_data(vm, 1); - map_check_ref(vm); - be_refpush(vm, 1); - be_pushstring(vm, "{"); - be_pushiter(vm, -2); /* map iterator use 1 register */ - while (be_iter_hasnext(vm, -3)) { - be_iter_next(vm, -3); - push_key(vm); /* key.tostring() */ - be_pushstring(vm, ": "); /* add ': ' */ - be_strconcat(vm, -5); - be_pop(vm, 1); - push_value(vm); /* value.tostring() */ - } - be_pop(vm, 1); /* pop iterator */ - be_pushstring(vm, "}"); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_refpop(vm); - be_return(vm); -} - -static int m_remove(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - map_check_data(vm, 2); - be_pushvalue(vm, 2); - be_data_remove(vm, -2); - be_return_nil(vm); -} - -static int m_item(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - map_check_data(vm, 2); - be_pushvalue(vm, 2); - if (!be_getindex(vm, -2)) { - be_raise(vm, "key_error", be_tostring(vm, 2)); - } - be_return(vm); -} - -static int m_setitem(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - map_check_data(vm, 3); - be_pushvalue(vm, 2); - be_pushvalue(vm, 3); - be_setindex(vm, -3); - be_return_nil(vm); -} - -static int m_find(bvm *vm) -{ - int argc = be_top(vm); - be_getmember(vm, 1, ".p"); - map_check_data(vm, 2); - be_pushvalue(vm, 2); - /* not find and has default value */ - if (!be_getindex(vm, -2) && argc >= 3) { - be_pushvalue(vm, 3); - } - be_return(vm); -} - -static int m_contains(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - map_check_data(vm, 2); - be_pushvalue(vm, 2); - be_pushbool(vm, be_getindex(vm, -2)); - be_return(vm); -} - -static int m_insert(bvm *vm) -{ - bbool res; - be_getmember(vm, 1, ".p"); - map_check_data(vm, 3); - be_pushvalue(vm, 2); - be_pushvalue(vm, 3); - res = be_data_insert(vm, -3); - be_pushbool(vm, res); - be_return(vm); -} - -static int m_size(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - map_check_data(vm, 1); - be_pushint(vm, be_data_size(vm, -1)); - be_return(vm); -} - -static int m_tobool(bvm *vm) -{ - be_getmember(vm, 1, ".p"); - map_check_data(vm, 1); - be_pushbool(vm, be_data_size(vm, -1) > 0); - be_return(vm); -} - -static int iter_closure(bvm *vm) -{ - /* for better performance, we operate the upvalues - * directly without using by the stack. */ - bntvclos *func = var_toobj(vm->cf->func); - bvalue *uv0 = be_ntvclos_upval(func, 0)->value; /* list value */ - bvalue *uv1 = be_ntvclos_upval(func, 1)->value; /* iter value */ - bmapiter iter = var_toobj(uv1); - bmapnode *next = be_map_next(var_toobj(uv0), &iter); - if (next == NULL) { - be_stop_iteration(vm); - be_return_nil(vm); /* will not be executed */ - } - var_setobj(uv1, BE_COMPTR, iter); /* set upvale[1] (iter value) */ - /* push next value to top */ - var_setval(vm->top, &next->value); - be_incrtop(vm); - be_return(vm); -} - -static int m_iter(bvm *vm) -{ - be_pushntvclosure(vm, iter_closure, 2); - be_getmember(vm, 1, ".p"); - be_setupval(vm, -2, 0); - be_pushiter(vm, -1); - be_setupval(vm, -3, 1); - be_pop(vm, 2); - be_return(vm); -} - -static int keys_iter_closure(bvm *vm) -{ - /* for better performance, we operate the upvalues - * directly without using by the stack. */ - bntvclos *func = var_toobj(vm->cf->func); - bvalue *uv0 = be_ntvclos_upval(func, 0)->value; /* list value */ - bvalue *uv1 = be_ntvclos_upval(func, 1)->value; /* iter value */ - bmapiter iter = var_toobj(uv1); - bmapnode *next = be_map_next(var_toobj(uv0), &iter); - if (next == NULL) { - be_stop_iteration(vm); - be_return_nil(vm); /* will not be executed */ - } - var_setobj(uv1, BE_COMPTR, iter); /* set upvale[1] (iter value) */ - /* push next value to top */ - var_setobj(vm->top, next->key.type, next->key.v.p); - be_incrtop(vm); - be_return(vm); -} - -static int m_keys(bvm *vm) -{ - be_pushntvclosure(vm, keys_iter_closure, 2); - be_getmember(vm, 1, ".p"); - be_setupval(vm, -2, 0); - be_pushiter(vm, -1); - be_setupval(vm, -3, 1); - be_pop(vm, 2); - be_return(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -void be_load_maplib(bvm *vm) -{ - static const bnfuncinfo members[] = { - { ".p", NULL }, - { "init", m_init }, - { "tostring", m_tostring }, - { "remove", m_remove }, - { "item", m_item }, - { "setitem", m_setitem }, - { "find", m_find }, - { "contains", m_contains }, - { "has", m_contains }, /* deprecated */ - { "size", m_size }, - { "insert", m_insert }, - { "iter", m_iter }, - { "keys", m_keys }, - { "tobool", m_tobool } - { NULL, NULL } - }; - be_regclass(vm, "map", members); -} -#else -/* @const_object_info_begin -class be_class_map (scope: global, name: map) { - .p, var - init, func(m_init) - tostring, func(m_tostring) - remove, func(m_remove) - item, func(m_item) - setitem, func(m_setitem) - find, func(m_find) - contains, func(m_contains) - has, func(m_contains) - size, func(m_size) - insert, func(m_insert) - iter, func(m_iter) - keys, func(m_keys) - tobool, func(m_tobool) -} -@const_object_info_end */ -#include "../generate/be_fixed_be_class_map.h" -#endif diff --git a/lib/libesp32/Berry/src/be_mathlib.c b/lib/libesp32/Berry/src/be_mathlib.c deleted file mode 100644 index 0cef918e0edf..000000000000 --- a/lib/libesp32/Berry/src/be_mathlib.c +++ /dev/null @@ -1,438 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include -#include -#include - -#if BE_USE_MATH_MODULE - -#ifdef M_PI - #undef M_PI -#endif -#define M_PI 3.141592653589793238462643383279 - -#if BE_INTGER_TYPE == 0 /* int */ - #define M_IMAX INT_MAX - #define M_IMIN INT_MIN -#elif BE_INTGER_TYPE == 1 /* long */ - #define M_IMAX LONG_MAX - #define M_IMIN LONG_MIN -#else /* int64_t (long long) */ - #define M_IMAX LLONG_MAX - #define M_IMIN LLONG_MIN -#endif - -#if BE_USE_SINGLE_FLOAT - #define mathfunc(func) func##f -#else - #define mathfunc(func) func -#endif - -static int m_isnan(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isreal(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushbool(vm, isnan(x)); - } else { - be_pushbool(vm, bfalse); - } - be_return(vm); -} - -static int m_isinf(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isreal(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushbool(vm, isinf(x)); - } else { - be_pushbool(vm, bfalse); - } - be_return(vm); -} - -static int m_abs(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(fabs)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_ceil(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(ceil)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_floor(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(floor)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_round(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(round)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_sin(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(sin)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_cos(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(cos)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_tan(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(tan)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_asin(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(asin)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_acos(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(acos)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_atan(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(atan)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_atan2(bvm *vm) -{ - if (be_top(vm) >= 2 && be_isnumber(vm, 1) && be_isnumber(vm, 2)) { - breal y = be_toreal(vm, 1); - breal x = be_toreal(vm, 2); - be_pushreal(vm, mathfunc(atan2)(y, x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_sinh(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(sinh)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_cosh(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(cosh)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_tanh(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(tanh)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_sqrt(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(sqrt)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_exp(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(exp)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_log(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(log)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_log10(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, mathfunc(log10)(x)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_deg(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, x * (breal)(180.0 / M_PI)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_rad(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isnumber(vm, 1)) { - breal x = be_toreal(vm, 1); - be_pushreal(vm, x * (breal)(M_PI / 180.0)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_pow(bvm *vm) -{ - if (be_top(vm) >= 2 && be_isnumber(vm, 1) && be_isnumber(vm, 2)) { - breal x = be_toreal(vm, 1); - breal y = be_toreal(vm, 2); - be_pushreal(vm, mathfunc(pow)(x, y)); - } else { - be_pushreal(vm, (breal)0.0); - } - be_return(vm); -} - -static int m_srand(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isint(vm, 1)) { - srand((unsigned int)be_toint(vm, 1)); - } - be_return_nil(vm); -} - -static int m_rand(bvm *vm) -{ - be_pushint(vm, rand()); - be_return(vm); -} - -/* check that all arguments are either int or real, and return true if at least one is real */ -static int m_check_int_or_has_real(bvm *vm) -{ - int argc = be_top(vm); - int has_real = 0; - for (int i = 1; i <= argc; ++i) { - if (be_isreal(vm, i)) { - has_real = 1; - } else if (!be_isint(vm, i)) { - be_raise(vm, "type_error", "arguments must be numbers"); - } - } - return has_real; -} - -static int m_min_max(bvm *vm, int is_min) { - int argc = be_top(vm); - if (argc > 0) { - /* see if at least one argument is float, else they are all ints */ - int has_real = m_check_int_or_has_real(vm); - if (has_real) { - breal bound = be_toreal(vm, 1); - for (int i = 2; i <= argc; ++i) { - breal x = be_toreal(vm, i); - if (is_min ? (x < bound) : (x > bound)) { - bound = x; - } - } - be_pushreal(vm, bound); - } else { - bint bound = be_toint(vm, 1); - for (int i = 2; i <= argc; ++i) { - bint x = be_toint(vm, i); - if (is_min ? (x < bound) : (x > bound)) { - bound = x; - } - } - be_pushint(vm, bound); - } - be_return(vm); - } - be_return_nil(vm); - -} - -int m_min(bvm *vm) -{ - return m_min_max(vm, 1); -} - -int m_max(bvm *vm) -{ - return m_min_max(vm, 0); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(math) { - be_native_module_function("isnan", m_isnan), - be_native_module_function("isinf", m_isinf), - be_native_module_function("abs", m_abs), - be_native_module_function("ceil", m_ceil), - be_native_module_function("floor", m_floor), - be_native_module_function("round", m_round), - be_native_module_function("sin", m_sin), - be_native_module_function("cos", m_cos), - be_native_module_function("tan", m_tan), - be_native_module_function("asin", m_asin), - be_native_module_function("acos", m_acos), - be_native_module_function("atan", m_atan), - be_native_module_function("atan2", m_atan2), - be_native_module_function("sinh", m_sinh), - be_native_module_function("cosh", m_cosh), - be_native_module_function("tanh", m_tanh), - be_native_module_function("sqrt", m_sqrt), - be_native_module_function("exp", m_exp), - be_native_module_function("log", m_log), - be_native_module_function("log10", m_log10), - be_native_module_function("deg", m_deg), - be_native_module_function("rad", m_rad), - be_native_module_function("pow", m_pow), - be_native_module_function("srand", m_srand), - be_native_module_function("rand", m_rand), - be_native_module_function("min", m_min), - be_native_module_function("max", m_max), - be_native_module_real("pi", M_PI), - be_native_module_real("nan", NAN), - be_native_module_real("inf", INFINITY), - be_native_module_int("imax", M_IMAX), - be_native_module_int("imin", M_IMIN), -}; - -be_define_native_module(math, NULL); -#else -/* @const_object_info_begin -module math (scope: global, depend: BE_USE_MATH_MODULE) { - isnan, func(m_isnan) - isinf, func(m_isinf) - abs, func(m_abs) - ceil, func(m_ceil) - floor, func(m_floor) - round, func(m_round) - sin, func(m_sin) - cos, func(m_cos) - tan, func(m_tan) - asin, func(m_asin) - acos, func(m_acos) - atan, func(m_atan) - atan2, func(m_atan2) - sinh, func(m_sinh) - cosh, func(m_cosh) - tanh, func(m_tanh) - sqrt, func(m_sqrt) - exp, func(m_exp) - log, func(m_log) - log10, func(m_log10) - deg, func(m_deg) - rad, func(m_rad) - pow, func(m_pow) - srand, func(m_srand) - rand, func(m_rand) - min, func(m_min) - max, func(m_max) - pi, real(M_PI) - nan, real(NAN) - inf, real(INFINITY) - imax, int(M_IMAX) - imin, int(M_IMIN) -} -@const_object_info_end */ -#include "../generate/be_fixed_math.h" -#endif - -#endif /* BE_USE_MATH_MODULE */ diff --git a/lib/libesp32/Berry/src/be_mem.c b/lib/libesp32/Berry/src/be_mem.c deleted file mode 100644 index 9d20ca055121..000000000000 --- a/lib/libesp32/Berry/src/be_mem.c +++ /dev/null @@ -1,372 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_mem.h" -#include "be_exec.h" -#include "be_vm.h" -#include "be_gc.h" -#include -#include - -#define GC_ALLOC (1 << 2) /* GC in alloc */ - -#ifdef BE_EXPLICIT_MALLOC - #define malloc BE_EXPLICIT_MALLOC -#endif - -#ifdef BE_EXPLICIT_FREE - #define free BE_EXPLICIT_FREE -#endif - -#ifdef BE_EXPLICIT_REALLOC - #define realloc BE_EXPLICIT_REALLOC -#endif - -#define POOL16_SIZE 16 -#define POOL32_SIZE 32 - -#ifdef _MSC_VER -#include -#pragma intrinsic(_BitScanForward) -#endif - -#if defined(__GNUC__) -#define popcount(v) __builtin_popcount(v) -#define ffs(v) __builtin_ffs(v) -#elif defined(_MSC_VER) -#define popcount(v) __popcnt(v) - -static int ffs(unsigned x) -{ - unsigned long i; - return _BitScanForward(&i, x) ? i : 0; -} -#else -/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */ -static int popcount(uint32_t n) -{ - n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u); - n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u); - n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu); - n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu); - n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu); - return n; -} - -#error "unsupport compiler for ffs()" -#endif - -static void* malloc_from_pool(bvm *vm, size_t size); -static void free_from_pool(bvm *vm, void* ptr, size_t old_size); - -BERRY_API void* be_os_malloc(size_t size) -{ - return malloc(size); -} - -BERRY_API void be_os_free(void *ptr) -{ - free(ptr); -} - -BERRY_API void* be_os_realloc(void *ptr, size_t size) -{ - return realloc(ptr, size); -} - -BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size) -{ - void *block = NULL; - // serial_debug("be_realloc ptr=%p old_size=%i new_size=%i\n", ptr, old_size, new_size); - - bbool gc_occured = bfalse; /* if allocation failed, retry after forced GC */ - if (old_size == new_size) { /* the block unchanged, this also captures creation of a zero byte object */ - return ptr; - } - /* from now on, block == NULL means allocation failure */ - - while (1) { - /* Case 1: new allocation */ -#if BE_USE_PERF_COUNTERS - vm->counter_mem_alloc++; -#endif - if (!ptr || (old_size == 0)) { - block = malloc_from_pool(vm, new_size); - } - - /* Case 2: deallocate */ - else if (new_size == 0) { -#if BE_USE_PERF_COUNTERS - vm->counter_mem_free++; -#endif - if (ptr == NULL) { return NULL; } /* safeguard */ - if (BE_USE_DEBUG_GC || comp_is_gc_debug(vm)) { - memset(ptr, 0xFF, old_size); /* fill the structure with invalid pointers */ - } - free_from_pool(vm, ptr, old_size); - break; /* early exit */ - } - - /* Case 3: reallocate with a different size */ - else if (new_size && old_size) { // TODO we already know they are not null TODO -#if BE_USE_PERF_COUNTERS - vm->counter_mem_realloc++; -#endif - if (new_size <= POOL32_SIZE || old_size <=POOL32_SIZE) { - /* complex case with different pools */ - if (new_size <= POOL16_SIZE && old_size <= POOL16_SIZE) { - // no change of slot - block = ptr; - break; - } else if (new_size > POOL16_SIZE && old_size > POOL16_SIZE && new_size <= POOL32_SIZE && old_size <= POOL32_SIZE) { - // no change of slot - block = ptr; - break; - } else { - /* one of the buffer is out of pool, the other not */ - block = malloc_from_pool(vm, new_size); - if (block) { - /* copy memory */ - size_t min_size = old_size < new_size ? old_size : new_size; - memmove(block, ptr, min_size); - // serial_debug("memmove from %p to %p size=%i\n", ptr, block, min_size); - free_from_pool(vm, ptr, old_size); - } - } - } else { - block = realloc(ptr, new_size); - // serial_debug("realloc from %p to %p size=%i", ptr, block, new_size); - } - } /* end of reallocation */ - - /* exit allocator, do we need to GC ? */ - if (block) { break; } /* all good */ - if (gc_occured) { /* already tried gc, can't do much anymore */ - be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */ - } - // serial_debug("be_realloc force_gc\n"); - /* force GC now */ - vm->gc.status |= GC_ALLOC; - be_gc_collect(vm); /* try to allocate again after GC */ - vm->gc.status &= ~GC_ALLOC; - gc_occured = btrue; /* don't try again GC */ - } - vm->gc.usage = vm->gc.usage + new_size - old_size; /* update allocated count */ - - // serial_debug("be_realloc ret=%p\n", block); - return block; -} - -BERRY_API void* be_move_to_aligned(bvm *vm, void *ptr, size_t size) { - (void)vm; - (void)size; -#if BE_USE_MEM_ALIGNED - if (size <= POOL32_SIZE) { - return ptr; /* if in memory pool, don't move it so be_free() will continue to work */ - } - void* iram = berry_malloc32(size); - if (iram) { - memcpy(iram, ptr, size); /* new_size is always smaller than initial mem zone */ - free(ptr); // TODO gc size is now wrong - return iram; - } -#endif - return ptr; -} - -/* Special allocator for structures under 32 bytes */ -typedef uint8_t mem16[16]; /* memory line of 16 bytes */ -typedef uint8_t mem32[32]; /* memory line of 32 bytes */ -#define POOL16_SLOTS 31 -#define POOL16_BITMAP_FULL ((1UL<gc.pool16; - while (pool16) { - /* look for an empty slot */ - if (pool16->bitmap != 0x0000) { - /* there is a free slot */ - int bit = ffs(pool16->bitmap) - 1; - if (bit >= 0) { - /* we found a free slot */ - // bitClear(pool16->bitmap, bit); - pool16->bitmap &= ~(1UL << bit); - // serial_debug("malloc_from_pool found slot in pool %p, bit %i, ptr=%p\n", pool16, bit, &pool16->lines[bit]); - return &pool16->lines[bit]; - } - } - pool16 = pool16->next; - } - /* no slot available, we allocate a new pool */ - pool16 = (gc16_t*) malloc(sizeof(gc16_t)); - if (!pool16) { return NULL; } /* out of memory */ - pool16->next = vm->gc.pool16; - pool16->bitmap = POOL16_BITMAP_FULL - 1; /* allocate first line */ - vm->gc.pool16 = pool16; /* insert at head of linked list */ - // serial_debug("malloc_from_pool allocated new pool %p, size=%i p=%p\n", pool16, sizeof(gc16_t), &pool16->lines[0]); - return &pool16->lines[0]; - } - - if (size <= POOL32_SIZE) { - /* allocate in pool 32 */ - gc32_t* pool32 = vm->gc.pool32; - while (pool32) { - /* look for an empty slot */ - if (pool32->bitmap != 0x0000) { - /* there is a free slot */ - int bit = ffs(pool32->bitmap) - 1; - if (bit >= 0) { - /* we found a free slot */ - // bitClear(pool32->bitmap, bit); - pool32->bitmap &= ~(1UL << bit); - // serial_debug("malloc_from_pool found slot in pool %p, bit %i, ptr=%p\n", pool32, bit, &pool32->lines[bit]); - return &pool32->lines[bit]; - } - } - pool32 = pool32->next; - } - /* no slot available, we allocate a new pool */ - pool32 = (gc32_t*) malloc(sizeof(gc32_t)); - if (!pool32) { return NULL; } /* out of memory */ - pool32->next = vm->gc.pool32; - pool32->bitmap = POOL32_BITMAP_FULL - 1; /* allocate first line */ - vm->gc.pool32 = pool32; /* insert at head of linked list */ - // serial_debug("malloc_from_pool allocated new pool %p, size=%i p=%p\n", pool32, sizeof(gc32_t), &pool32->lines[0]); - return &pool32->lines[0]; - } - - return malloc(size); /* default to system malloc */ -} - -static void free_from_pool(bvm *vm, void* ptr, size_t old_size) { - if (old_size <= POOL16_SIZE) { - gc16_t* pool16 = vm->gc.pool16; - while (pool16) { - int32_t offset = (uint8_t*)ptr - (uint8_t*) &pool16->lines[0]; - // serial_debug("free_from_pool ptr=%p pool=%p offset=%i\n", ptr,pool16, offset); - if ((offset >= 0) && (offset < POOL16_SLOTS*16) && ((offset & 0x0F) == 0)) { - int bit = offset >> 4; - // serial_debug("free_from_pool ptr=%p fond pool=%p bit=%i\n", ptr, pool16, bit); - // bitSet(pool16->bitmap, bit); - pool16->bitmap |= 1UL << bit; - return; - } - pool16 = pool16->next; - } - } - else if (old_size <= POOL32_SIZE) { - gc32_t* pool32 = vm->gc.pool32; - while (pool32) { - int32_t offset = (uint8_t*)ptr - (uint8_t*) &pool32->lines[0]; - // serial_debug("free_from_pool pool=%p offset=%i\n", pool32, offset); - if ((offset >= 0) && (offset < POOL16_SLOTS*16) && ((offset & 0x1F) == 0)) { - int bit = offset >> 5; - // serial_debug("free_from_pool ptr=%p fond pool=%p bit=%i\n", ptr, pool32, bit); - // bitSet(pool32->bitmap, bit); - pool32->bitmap |= 1UL << bit; - return; - } - pool32 = pool32->next; - } - } - else { - // serial_debug("free_from_pool free=%p\n", ptr); - free(ptr); - } -} - -BERRY_API void be_gc_memory_pools(bvm *vm) { - gc16_t** prev16 = &vm->gc.pool16; - gc16_t* pool16 = vm->gc.pool16; - while (pool16) { - if (pool16->bitmap == POOL16_BITMAP_FULL) { - /* pool is empty, we can free it */ - *prev16 = pool16->next; - gc16_t* pool_to_freed = pool16; - pool16 = pool16->next; /* move to next */ - free(pool_to_freed); - } else { - prev16 = &pool16->next; - pool16 = pool16->next; /* move to next */ - } - } - gc32_t** prev32 = &vm->gc.pool32; - gc32_t* pool32 = vm->gc.pool32; - while (pool32) { - if (pool32->bitmap == POOL32_BITMAP_FULL) { - /* pool is empty, we can free it */ - *prev32 = pool32->next; - gc32_t* pool_to_freed = pool32; - pool32 = pool32->next; /* move to next */ - free(pool_to_freed); - } else { - prev32 = &pool32->next; - pool32 = pool32->next; /* move to next */ - } - } -} - -BERRY_API void be_gc_init_memory_pools(bvm *vm) { - vm->gc.pool16 = NULL; - vm->gc.pool32 = NULL; -} - -BERRY_API void be_gc_free_memory_pools(bvm *vm) { - gc16_t* pool16 = vm->gc.pool16; - while (pool16) { - gc16_t* pool_to_freed = pool16; - pool16 = pool16->next; - be_os_free(pool_to_freed); - } - vm->gc.pool16 = NULL; - - gc32_t* pool32 = vm->gc.pool32; - while (pool32) { - gc32_t* pool_to_freed = pool32; - pool32 = pool32->next; - be_os_free(pool_to_freed); - } - vm->gc.pool32 = NULL; -} - -BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated) { - size_t used = 0; - size_t allocated = 0; - - gc16_t* pool16 = vm->gc.pool16; - while (pool16) { - allocated += POOL16_SLOTS; - used += POOL16_SLOTS - popcount(pool16->bitmap); - pool16 = pool16->next; - } - - gc32_t* pool32 = vm->gc.pool32; - while (pool32) { - allocated += POOL32_SLOTS; - used += POOL32_SLOTS - popcount(pool32->bitmap); - pool32 = pool32->next; - } - if (slots_used) { *slots_used = used; } - if (slots_allocated) { *slots_allocated = allocated; } -} diff --git a/lib/libesp32/Berry/src/be_mem.h b/lib/libesp32/Berry/src/be_mem.h deleted file mode 100644 index 9545cec49f71..000000000000 --- a/lib/libesp32/Berry/src/be_mem.h +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_MEM_H -#define BE_MEM_H - -#include "berry.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define be_malloc(vm, size) be_realloc((vm), NULL, 0, (size)) -#define be_free(vm, ptr, size) be_realloc((vm), (ptr), (size), 0) - -BERRY_API void* be_os_malloc(size_t size); -BERRY_API void be_os_free(void *ptr); -BERRY_API void* be_os_realloc(void *ptr, size_t size); -BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size); -BERRY_API void be_gc_memory_pools(bvm *vm); -BERRY_API void be_gc_free_memory_pools(bvm *vm); -BERRY_API void be_gc_init_memory_pools(bvm *vm); -BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated); - -/* The following moves a portion of memory to constraint regions with 32-bits read/write acess */ -/* Effective only if `BE_USE_MEM_ALIGNED` is set to `1`*/ -BERRY_API void* be_move_to_aligned(bvm *vm, void *ptr, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32/Berry/src/be_module.c b/lib/libesp32/Berry/src/be_module.c deleted file mode 100644 index f02b9dedbefd..000000000000 --- a/lib/libesp32/Berry/src/be_module.c +++ /dev/null @@ -1,498 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_module.h" -#include "be_string.h" -#include "be_strlib.h" -#include "be_list.h" -#include "be_exec.h" -#include "be_map.h" -#include "be_gc.h" -#include "be_mem.h" -#include "be_vm.h" -#include - -/* the maximum suffix length */ -#define SUFFIX_LEN 5 /* length of (.be .bec .so .dll) + 1 */ - -/* check POSIX platforms */ -#if defined(__linux__) || \ - defined(__APPLE__) || defined(__unix__) || defined(__CYGWIN__) - #define __POSIX_OS__ -#endif - -#if BE_USE_SHARED_LIB - #if defined(__POSIX_OS__) - #define DLL_SUFFIX ".so" - #elif defined(_WIN32) - #define DLL_SUFFIX ".dll" - #else - #define DLL_SUFFIX "" - #warning module: unsuppord OS - #endif -#endif - -extern BERRY_LOCAL const bntvmodule_t* const be_module_table[]; - -static bmodule* native_module(bvm *vm, const bntvmodule_t *nm, bvalue *dst); - -static const bntvmodule_t* find_native(bstring *path) -{ - const bntvmodule_t *module; - const bntvmodule_t* const *node = be_module_table; - for (; (module = *node) != NULL; ++node) { - if (!strcmp(module->name, str(path))) { - return module; - } - } - return NULL; -} - -static void insert_attrs(bvm *vm, bmap *table, const bntvmodule_t *nm) -{ - size_t i; - for (i = 0; i < nm->size; ++i) { - const bntvmodobj_t *node = nm->attrs + i; - bstring *name = be_newstr(vm, node->name); - bvalue *v = be_map_insertstr(vm, table, name, NULL); - be_assert(node->type <= BE_CMODULE); - switch (node->type) { - case BE_CNIL: - var_setnil(v); - break; - case BE_CINT: - var_setint(v, node->u.i); - break; - case BE_CREAL: - var_setreal(v, node->u.r); - break; - case BE_CBOOL: - var_setbool(v, node->u.b); - break; - case BE_CFUNCTION: - var_setntvfunc(v, node->u.f); - break; - case BE_CSTRING: - var_setstr(v, be_newstr(vm, node->u.s)); - break; - case BE_CMODULE: - native_module(vm, node->u.o, v); - break; - default: /* error */ - break; - } - } -} - -static bmodule* new_module(bvm *vm, const bntvmodule_t *nm) -{ - bgcobject *gco = be_gcnew(vm, BE_MODULE, bmodule); - bmodule *obj = cast_module(gco); - if (obj) { - var_setmodule(vm->top, obj); - be_incrtop(vm); - obj->info.native = nm; - obj->table = NULL; /* gc protection */ - obj->table = be_map_new(vm); - insert_attrs(vm, obj->table, nm); - be_map_compact(vm, obj->table); /* clear space */ - be_stackpop(vm, 1); - } - return obj; -} - -static bmodule* native_module(bvm *vm, const bntvmodule_t *nm, bvalue *dst) -{ - if (nm) { - bmodule *obj; - if (nm->module) { - obj = (bmodule *)nm->module; - } else { /* new module */ - obj = new_module(vm, nm); - } - if (obj && dst) { - var_setmodule(dst, obj); - } - return obj; - } - return NULL; -} - -static char* fixpath(bvm *vm, bstring *path, size_t *size) -{ - char *buffer; - const char *split, *base; -#if BE_DEBUG_SOURCE_FILE - bvalue *func = vm->cf->func; - bclosure *cl = var_toobj(func); - if (var_isclosure(func)) { - base = str(cl->proto->source); /* get the source file path */ - } else { - base = "/"; - } -#else - base = "/"; -#endif - split = be_splitpath(base); - *size = split - base + (size_t)str_len(path) + SUFFIX_LEN; - buffer = be_malloc(vm, *size); - strncpy(buffer, base, split - base); - strcpy(buffer + (split - base), str(path)); - return buffer; -} - -static char* conpath(bvm *vm, bstring *path1, bstring *path2, size_t *size) -{ - char *buffer; - int len1 = str_len(path1); - *size = (size_t)len1 + (size_t)str_len(path2) + 1 + SUFFIX_LEN; - buffer = be_malloc(vm, *size); - strcpy(buffer, str(path1)); - buffer[len1] = '/'; - strcpy(buffer + len1 + 1, str(path2)); - return buffer; -} - -static int open_script(bvm *vm, char *path) -{ - int res = be_loadmodule(vm, path); - if (res == BE_OK) - be_call(vm, 0); - return res; -} - -#if BE_USE_SHARED_LIB -static int open_dllib(bvm *vm, char *path) -{ - int res = be_loadlib(vm, path); - if (res == BE_OK) - be_call(vm, 0); - return res; -} -#endif - -static int open_libfile(bvm *vm, char *path, size_t size) -{ - int res, idx = 0; - const char *sfxs[] = { "", ".bec", ".be" }; - do { - strcpy(path + size - SUFFIX_LEN, sfxs[idx]); - res = open_script(vm, path); - } while (idx++ < 2 && res == BE_IO_ERROR); - if (res == BE_IO_ERROR) { -#if BE_USE_SHARED_LIB - strcpy(path + size - SUFFIX_LEN, DLL_SUFFIX); - res = open_dllib(vm, path); -#endif - } - be_free(vm, path, size); - return res; -} - -static int load_path(bvm *vm, bstring *path, bstring *mod) -{ - size_t size; - char *fullpath = conpath(vm, path, mod, &size); - return open_libfile(vm, fullpath, size); -} - -static int load_cwd(bvm *vm, bstring *path) -{ - size_t size; - char *fullpath = fixpath(vm, path, &size); - return open_libfile(vm, fullpath, size); -} - -static int load_package(bvm *vm, bstring *path) -{ - int res = load_cwd(vm, path); /* load from current directory */ - if (res == BE_IO_ERROR && vm->module.path) { - blist *list = vm->module.path; - bvalue *v = be_list_end(list) - 1; - bvalue *first = be_list_data(list); - for (; res == BE_IO_ERROR && v >= first; v--) { - if (var_isstr(v)) { - res = load_path(vm, var_tostr(v), path); - } - } - } - return res; -} - -static int load_native(bvm *vm, bstring *path) -{ - const bntvmodule_t *nm = find_native(path); - bmodule *mod = native_module(vm, nm, NULL); - if (mod != NULL) { - /* the pointer vm->top may be changed */ - var_setmodule(vm->top, mod); - be_incrtop(vm); - return BE_OK; - } - return BE_IO_ERROR; -} - -static bvalue* load_cached(bvm *vm, bstring *path) -{ - bvalue *v = NULL; - if (vm->module.loaded) { - v = be_map_findstr(vm, vm->module.loaded, path); - if (v) { - *vm->top = *v; - be_incrtop(vm); - } - } - return v; -} - -void be_cache_module(bvm *vm, bstring *name) -{ - bvalue *v; - if (vm->module.loaded == NULL) { - vm->module.loaded = be_map_new(vm); - } - v = be_map_insertstr(vm, vm->module.loaded, name, NULL); - *v = vm->top[-1]; -} - -/* Try to run 'init(m)' function of module. Module is already loaded. */ -static void module_init(bvm *vm) { - if (be_ismodule(vm, -1)) { - if (be_getmember(vm, -1, "init")) { - /* found, call it with current module as parameter */ - be_pushvalue(vm, -2); - be_call(vm, 1); - /* the result of init() is cached and returned */ - be_pop(vm, 1); - be_remove(vm, -2); /* remove initial module */ - } else { - be_pop(vm, 1); - } - } -} - -/* load module to vm->top */ -int be_module_load(bvm *vm, bstring *path) -{ - int res = BE_OK; - if (!load_cached(vm, path)) { - res = load_native(vm, path); - if (res == BE_IO_ERROR) - res = load_package(vm, path); - if (res == BE_OK) { - /* on first load of the module, try running the '()' function */ - module_init(vm); - be_cache_module(vm, path); - } - } - return res; -} - -BERRY_API bbool be_getmodule(bvm *vm, const char *k) -{ - int res = be_module_load(vm, be_newstr(vm, k)); - return res == BE_OK; -} - -bmodule* be_module_new(bvm *vm) -{ - bgcobject *gco = be_gcnew(vm, BE_MODULE, bmodule); - bmodule *obj = cast_module(gco); - if (obj) { - var_setmodule(vm->top, obj); - be_incrtop(vm); - obj->info.native = NULL; - obj->table = NULL; /* gc protection */ - obj->table = be_map_new(vm); - be_stackpop(vm, 1); - } - return obj; -} - -void be_module_delete(bvm *vm, bmodule *module) -{ - be_free(vm, module, sizeof(bmodule)); -} - -int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst) -{ - bvalue *member = be_map_findstr(vm, module->table, attr); - if (!member) { /* try the 'member' function */ - /* if 'init' does not exist, don't call member() */ - if (strcmp(str(attr), "init") == 0) { - var_setntvfunc(dst, be_default_init_native_function); - return var_primetype(dst); - } - member = be_map_findstr(vm, module->table, str_literal(vm, "member")); - if (member && var_basetype(member) == BE_FUNCTION) { - bvalue *top = vm->top; - top[0] = *member; - var_setstr(&top[1], attr); - vm->top += 2; /* prevent collection results */ - be_dofunc(vm, top, 1); /* call method 'method' */ - vm->top -= 2; - *dst = *vm->top; /* copy result to R(A) */ - - int type = var_type(dst); - if (type == BE_MODULE) { - /* check if the module is named `undefined` */ - bmodule *mod = var_toobj(dst); - if (strcmp(be_module_name(mod), "undefined") == 0) { - return BE_NONE; /* if the return value is module `undefined`, consider it is an error */ - } - } - return type; - } - return BE_NONE; - } - *dst = *member; - return var_type(dst); -} - -bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src) -{ - be_assert(src); - bmap *attrs = module->table; - if (!gc_isconst(attrs)) { - bvalue *v = be_map_findstr(vm, attrs, attr); - if (v == NULL) { - v = be_map_insertstr(vm, attrs, attr, NULL); - } - if (v) { - *v = *src; - return btrue; - } - } else { - /* if not writable, try 'setmember' */ - int type = be_module_attr(vm, module, str_literal(vm, "setmember"), vm->top); - if (basetype(type) == BE_FUNCTION) { - bvalue *top = vm->top; - // top[0] already has 'member' - var_setstr(&top[1], attr); /* attribute name */ - top[2] = *src; /* new value */ - vm->top += 3; /* prevent collection results */ - be_dofunc(vm, top, 2); /* call method 'setmember' */ - vm->top -= 3; - int type = var_type(vm->top); - if (type == BE_BOOL) { - bbool ret = var_tobool(vm->top); - if (!ret) { - return bfalse; - } - } else if (type == BE_MODULE) { - /* check if the module is named `undefined` */ - bmodule *mod = var_toobj(vm->top); - if (strcmp(be_module_name(mod), "undefined") == 0) { - return bfalse; /* if the return value is module `undefined`, consider it is an error */ - } - } - return btrue; - } - } - return bfalse; -} - -const char* be_module_name(const bmodule *module) -{ - if (gc_isconst(module)) { - return module->info.name; - } - if (gc_exmark(module) & BE_MODULE_NAME) { - return str(module->info.sname); - } - if (module->info.native) { - return module->info.native->name; - } - return NULL; -} - -bbool be_module_setname(bmodule *module, bstring *name) -{ - if (!gc_isconst(module)) { - module->info.sname = name; - gc_setexmark(module, BE_MODULE_NAME); - return btrue; - } - return bfalse; -} - -static blist* pathlist(bvm *vm) -{ - if (!vm->module.path) { - vm->module.path = be_list_new(vm); - } - return vm->module.path; -} - -/* push the path list to the top */ -BERRY_API void be_module_path(bvm *vm) -{ - blist *list = pathlist(vm); - bvalue *reg = be_incrtop(vm); - var_setlist(reg, list); -} - -BERRY_API void be_module_path_set(bvm *vm, const char *path) -{ - blist *list = pathlist(vm); - bvalue *value = be_list_push(vm, list, NULL); - var_setnil(value); - var_setstr(value, be_newstr(vm, path)) -} - -/* shared library support */ -#if BE_USE_SHARED_LIB - -#if defined(__POSIX_OS__) -#include - -#if defined(__GNUC__) - #define cast_func(f) (__extension__(bntvfunc)(f)) -#else - #define cast_func(f) ((bntvfunc)(f)) -#endif - -/* load shared library */ -BERRY_API int be_loadlib(bvm *vm, const char *path) -{ - void *handle = dlopen(path, RTLD_LAZY); - bntvfunc func = cast_func(dlsym(handle, "berry_export")); - if (func == NULL) { - return BE_IO_ERROR; - } - be_pushntvfunction(vm, func); - return BE_OK; -} -#elif defined(_WIN32) -#include -#include - -BERRY_API int be_loadlib(bvm *vm, const char *path) -{ - HINSTANCE handle = LoadLibrary(path); - if (handle) { - union { - FARPROC proc; - bntvfunc func; - } u; - u.proc = GetProcAddress(handle, "berry_export"); - if (u.func != NULL) { - be_pushntvfunction(vm, u.func); - return BE_OK; - } - } - return BE_IO_ERROR; -} -#else -BERRY_API int be_loadlib(bvm *vm, const char *path) -{ - (void)vm, (void)path; - return BE_IO_ERROR; -} -#endif - -#endif /* BE_USE_SHARED_LIB */ diff --git a/lib/libesp32/Berry/src/be_module.h b/lib/libesp32/Berry/src/be_module.h deleted file mode 100644 index 89ae682ae922..000000000000 --- a/lib/libesp32/Berry/src/be_module.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_MODULE_H -#define BE_MODULE_H - -#include "be_object.h" - -#define BE_MODULE_NAME 1 - -typedef struct bmodule { - bcommon_header; - bmap *table; - union infodata { - const bntvmodule_t *native; - const char *name; - const bstring *sname; -#ifdef __cplusplus - BE_CONSTEXPR infodata(const char *name) : name(name) {} -#endif - } info; - bgcobject *gray; /* for gc gray list */ -#ifdef __cplusplus - BE_CONSTEXPR bmodule(bmap *tab, const char *name) : - next(0), type(BE_MODULE), marked(GC_CONST), - table(tab), info(infodata(name)), gray(0) {} -#endif -} bmodule; - -bmodule* be_module_new(bvm *vm); -void be_module_delete(bvm *vm, bmodule *module); -int be_module_load(bvm *vm, bstring *path); -void be_cache_module(bvm *vm, bstring *name); -int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst); -bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src); -const char* be_module_name(const bmodule *module); -bbool be_module_setname(bmodule *module, bstring *name); - -#endif diff --git a/lib/libesp32/Berry/src/be_object.c b/lib/libesp32/Berry/src/be_object.c deleted file mode 100644 index aa2f7179966d..000000000000 --- a/lib/libesp32/Berry/src/be_object.c +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_exec.h" -#include "be_mem.h" -#include "be_gc.h" -#include "be_vm.h" - -#define cast_comobj(o) gc_cast(o, BE_COMOBJ, bcommomobj) - -const char* be_vtype2str(bvalue *v) -{ - switch(var_primetype(v)) { - case BE_NIL: return "nil"; - case BE_INT: return "int"; - case BE_REAL: return "real"; - case BE_BOOL: return "bool"; - case BE_CLOSURE: case BE_NTVCLOS: case BE_CTYPE_FUNC: - case BE_NTVFUNC: return "function"; - case BE_PROTO: return "proto"; - case BE_CLASS: return "class"; - case BE_STRING: return "string"; - case BE_LIST: return "list"; - case BE_MAP: return "map"; - case BE_INSTANCE: return "instance"; - case BE_MODULE: return "module"; - case BE_INDEX: return "var"; - case BE_COMPTR: return "ptr"; - default: return "invalid type"; - } -} - -bvalue* be_indexof(bvm *vm, int idx) -{ - if (idx > 0) { /* absolute index */ - be_assert(vm->reg + idx <= vm->top); - return vm->reg + idx - 1; - } - /* relative index */ - be_assert(vm->top + idx >= vm->reg); - return vm->top + idx; -} - -BERRY_API void be_newcomobj(bvm *vm, void *data, bntvfunc destroy) -{ - bcommomobj *obj; - bgcobject *gco = be_gcnew(vm, BE_COMOBJ, bcommomobj); - if ((obj = cast_comobj(gco)) != NULL) { - bvalue* top = be_incrtop(vm); - obj->data = data; - obj->destroy = destroy; - var_setobj(top, BE_COMOBJ, obj); - } -} - -void be_commonobj_delete(bvm *vm, bgcobject *obj) -{ - bcommomobj *co = cast_comobj(obj); - if (co) { - if (co->destroy && co->data) { - be_pushntvfunction(vm, co->destroy); - be_pushcomptr(vm, co->data); - be_call(vm, 1); - be_pop(vm, 2); - } - be_free(vm, co, sizeof(bcommomobj)); - } -} - -/* generic destroy method for comobj, just call be_os_free() on the pointer */ -int be_commonobj_destroy_generic(bvm* vm) -{ - int argc = be_top(vm); - if (argc > 0) { - void * obj = be_tocomptr(vm, 1); - if (obj != NULL) { be_os_free(obj); } - } - be_return_nil(vm); -} diff --git a/lib/libesp32/Berry/src/be_object.h b/lib/libesp32/Berry/src/be_object.h deleted file mode 100644 index 1c8d405725a6..000000000000 --- a/lib/libesp32/Berry/src/be_object.h +++ /dev/null @@ -1,267 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_OBJECT_H -#define BE_OBJECT_H - -#include "berry.h" - -/* basic types, do not change value */ -#define BE_NONE -256 /* unknown type */ -#define BE_NIL 0 -#define BE_INT 1 -#define BE_REAL 2 -#define BE_BOOL 3 -#define BE_COMPTR 4 /* common pointer */ -#define BE_INDEX 5 /* index for instance variable, previously BE_INT */ -#define BE_FUNCTION 6 - -#define BE_GCOBJECT 16 /* from this type can be gced */ -#define BE_GCOBJECT_MAX (3<<5) /* 96 - from this type can't be gced */ - -#define BE_STRING 16 -#define BE_CLASS 17 -#define BE_INSTANCE 18 -#define BE_PROTO 19 -#define BE_LIST 20 -#define BE_MAP 21 -#define BE_MODULE 22 -#define BE_COMOBJ 23 /* common object */ - -#define BE_NTVFUNC ((0 << 5) | BE_FUNCTION) /* 6 - cannot be gced */ -#define BE_CLOSURE ((1 << 5) | BE_FUNCTION) /* 38 - can be gced */ -#define BE_NTVCLOS ((2 << 5) | BE_FUNCTION) /* 70 - can be gced*/ -#define BE_CTYPE_FUNC ((3 << 5) | BE_FUNCTION) /* 102 - cannot be gced */ -#define BE_STATIC (1 << 7) /* 128 */ - -/* values for bproto.varg */ -#define BE_VA_VARARG (1 << 0) /* function has variable number of arguments */ -#define BE_VA_METHOD (1 << 1) /* function is a method (this is only a hint) */ -#define BE_VA_STATICMETHOD (1 << 2) /* the function is a static method and has the class as implicit '_class' variable */ -#define BE_VA_SHARED_KTAB (1 << 3) /* the funciton has a shared consolidated ktab */ -#define BE_VA_NOCOMPACT (1 << 4) /* the funciton has a shared consolidated ktab */ -#define array_count(a) (sizeof(a) / sizeof((a)[0])) - -#define bcommon_header \ - struct bgcobject *next; \ - bbyte type; \ - bbyte marked - -#define bstring_header \ - bcommon_header; \ - bbyte extra; \ - bbyte slen - -typedef struct bgcobject { - bcommon_header; -} bgcobject; - -typedef struct bclosure bclosure; -typedef struct bntvclos bntvclos; -typedef struct bclass bclass; -typedef struct binstance binstance; -typedef struct binstance_arg3 binstance_arg3; -typedef struct blist blist; -typedef struct bmap bmap; -typedef struct bupval bupval; - -typedef uint32_t binstruction; - -typedef struct bstring { - bstring_header; -} bstring; - -/* the definition of the vector and stack data structures. - * in fact, the stack is implemented by vector. */ -typedef struct bvector { - int capacity; /* the number of elements that the vector can store */ - int size; /* the size of each element (bytes) */ - int count; /* number of elements of the vector */ - void *data; /* the data block pointer, if vector is empty, - it will point to the first element */ - void *end; /* pointer to the last element, if the vector is empty, - the end pointer will be smaller than the data pointer */ -} bvector, bstack; - -/* berry value data union, a berry value is always described - * by the data structure contained in the bvaldata union. */ -union bvaldata { - bbool b; /* boolean */ - breal r; /* real number */ - bint i; /* integer number */ - void *p; /* object pointer */ - const void *c; /* const object pointer */ - bstring *s; /* string pointer */ - bgcobject *gc; /* GC object */ - bntvfunc nf; /* native C function */ -#ifdef __cplusplus - BE_CONSTEXPR bvaldata(bbool v) : b(v) {} - BE_CONSTEXPR bvaldata(breal v) : r(v) {} - BE_CONSTEXPR bvaldata(bint v) : i(v) {} - BE_CONSTEXPR bvaldata(void *v) : p(v) {} - BE_CONSTEXPR bvaldata(const void *v) : c(v) {} - BE_CONSTEXPR bvaldata(bntvfunc v) : nf(v) {} -#endif -}; - -/* berry value. for simple types, the value of the data is stored, - * while the complex type stores a reference to the data. */ -typedef struct bvalue { - union bvaldata v; /* the value data */ - int type; /* the value type */ -} bvalue; - -typedef struct { -#if BE_DEBUG_VAR_INFO - bstring *name; -#endif - bbyte instack; - bbyte idx; -} bupvaldesc; - -typedef struct { -#if BE_DEBUG_RUNTIME_INFO > 1 - uint16_t linenumber; - uint16_t endpc; -#else - int linenumber; - int endpc; -#endif -} blineinfo; - -typedef struct { - bstring *name; -#if BE_DEBUG_RUNTIME_INFO > 1 - uint16_t beginpc; - uint16_t endpc; -#else - int beginpc; - int endpc; -#endif -} bvarinfo; - -typedef struct bproto { - bcommon_header; - bbyte nstack; /* number of stack size by this function */ - bbyte nupvals; /* upvalue count */ - bbyte argc; /* argument count */ - bbyte varg; /* variable argument position + 1 */ - int16_t codesize; /* code size */ - int16_t nconst; /* constants count */ - int16_t nproto; /* proto count */ - bgcobject *gray; /* for gc gray list */ - bupvaldesc *upvals; - bvalue *ktab; /* constants table */ - struct bproto **ptab; /* proto table */ - binstruction *code; /* instructions sequence */ - bstring *name; /* function name */ -#if BE_DEBUG_SOURCE_FILE - bstring *source; /* source file name */ -#endif -#if BE_DEBUG_RUNTIME_INFO /* debug information */ - blineinfo *lineinfo; - int nlineinfo; -#endif -#if BE_DEBUG_VAR_INFO - bvarinfo *varinfo; - int nvarinfo; -#endif -} bproto; - -/* berry closure */ -struct bclosure { - bcommon_header; - bbyte nupvals; - bgcobject *gray; /* for gc gray list */ - bproto *proto; - bupval *upvals[1]; -}; - -/* C native function or closure */ -struct bntvclos { - bcommon_header; - bbyte nupvals; - bgcobject *gray; /* for gc gray list */ - bntvfunc f; -}; - -/* common object */ -typedef struct { - bcommon_header; - void *data; - bntvfunc destroy; -} bcommomobj; - -struct blexer; -typedef const char* (*breader)(struct blexer*, void*, size_t*); - -#define cast(_T, _v) ((_T)(_v)) -#define cast_int(_v) cast(int, _v) -#define cast_bool(_v) cast(bbool, _v) -#define basetype(_t) ((_t) & 0x1F) - -#define var_type(_v) ((_v)->type) -#define var_basetype(_v) basetype((_v)->type) -#define var_primetype(_v) (var_type(_v) & ~BE_STATIC) -#define var_isstatic(_v) ((var_type(_v) & BE_STATIC) == BE_STATIC) -#define var_istype(_v, _t) (var_primetype(_v) == _t) -#define var_settype(_v, _t) ((_v)->type = _t) -#define var_markstatic(_v) var_settype(_v, var_type(_v) | BE_STATIC) -#define var_clearstatic(_v) var_settype(_v, var_type(_v) & ~BE_STATIC) -#define var_setobj(_v, _t, _o) { (_v)->v.p = _o; var_settype(_v, _t); } - -#define var_isnil(_v) var_istype(_v, BE_NIL) -#define var_isbool(_v) var_istype(_v, BE_BOOL) -#define var_isint(_v) var_istype(_v, BE_INT) -#define var_isreal(_v) var_istype(_v, BE_REAL) -#define var_isstr(_v) var_istype(_v, BE_STRING) -#define var_isclosure(_v) var_istype(_v, BE_CLOSURE) -#define var_isntvclos(_v) var_istype(_v, BE_NTVCLOS) -#define var_isntvfunc(_v) var_istype(_v, BE_NTVFUNC) -#define var_isfunction(_v) (var_basetype(_v) == BE_FUNCTION) -#define var_isproto(_v) var_istype(_v, BE_PROTO) -#define var_isclass(_v) var_istype(_v, BE_CLASS) -#define var_isinstance(_v) var_istype(_v, BE_INSTANCE) -#define var_islist(_v) var_istype(_v, BE_LIST) -#define var_ismap(_v) var_istype(_v, BE_MAP) -#define var_ismodule(_v) var_istype(_v, BE_MODULE) -#define var_isindex(_v) var_istype(_v, BE_INDEX) -#define var_iscomptr(_v) var_istype(_v, BE_COMPTR) -#define var_isnumber(_v) (var_isint(_v) || var_isreal(_v)) - -#define var_setnil(_v) var_settype(_v, BE_NIL) -#define var_setval(_v, _s) (*(_v) = *(_s)) -#define var_setbool(_v, _b) { var_settype(_v, BE_BOOL); (_v)->v.b = (bbool)(_b); } -#define var_setint(_v, _i) { var_settype(_v, BE_INT); (_v)->v.i = (_i); } -#define var_setreal(_v, _r) { var_settype(_v, BE_REAL); (_v)->v.r = (_r); } -#define var_setstr(_v, _s) var_setobj(_v, BE_STRING, _s) -#define var_setinstance(_v, _o) var_setobj(_v, BE_INSTANCE, _o) -#define var_setclass(_v, _o) var_setobj(_v, BE_CLASS, _o) -#define var_setclosure(_v, _o) var_setobj(_v, BE_CLOSURE, _o) -#define var_setntvclos(_v, _o) var_setobj(_v, BE_NTVCLOS, _o) -#define var_setntvfunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_NTVFUNC); } -#define var_setlist(_v, _o) var_setobj(_v, BE_LIST, _o) -#define var_setmap(_v, _o) var_setobj(_v, BE_MAP, _o) -#define var_setmodule(_v, _o) var_setobj(_v, BE_MODULE, _o) -#define var_setindex(_v, _i) { var_settype(_v, BE_INDEX); (_v)->v.i = (_i); } -#define var_setproto(_v, _o) var_setobj(_v, BE_PROTO, _o) - -#define var_tobool(_v) ((_v)->v.b) -#define var_toint(_v) ((_v)->v.i) -#define var_toreal(_v) ((_v)->v.r) -#define var_tostr(_v) ((_v)->v.s) -#define var_togc(_v) ((_v)->v.gc) -#define var_toobj(_v) ((_v)->v.p) -#define var_tontvfunc(_v) ((_v)->v.nf) -#define var_toidx(_v) cast_int(var_toint(_v)) - -const char* be_vtype2str(bvalue *v); -bvalue* be_indexof(bvm *vm, int idx); -void be_commonobj_delete(bvm *vm, bgcobject *obj); -int be_commonobj_destroy_generic(bvm* vm); - -#endif diff --git a/lib/libesp32/Berry/src/be_opcodes.h b/lib/libesp32/Berry/src/be_opcodes.h deleted file mode 100644 index 12c3781e0645..000000000000 --- a/lib/libesp32/Berry/src/be_opcodes.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -/* define opcode, don't change order */ -/* opcode parameters description */ -OPCODE(ADD), /* A, B, C | R(A) <- RK(B) + RK(C) */ -OPCODE(SUB), /* A, B, C | R(A) <- RK(B) - RK(C) */ -OPCODE(MUL), /* A, B, C | R(A) <- RK(B) * RK(C) */ -OPCODE(DIV), /* A, B, C | R(A) <- RK(B) / RK(C) */ -OPCODE(MOD), /* A, B, C | R(A) <- RK(B) % RK(C) */ -OPCODE(LT), /* A, B, C | R(A) <- RK(B) < RK(C) */ -OPCODE(LE), /* A, B, C | R(A) <- RK(B) <= RK(C) */ -OPCODE(EQ), /* A, B, C | R(A) <- RK(B) == RK(C) */ -OPCODE(NE), /* A, B, C | R(A) <- RK(B) != RK(C) */ -OPCODE(GT), /* A, B, C | R(A) <- RK(B) > RK(C) */ -OPCODE(GE), /* A, B, C | R(A) <- RK(B) >= RK(C) */ -OPCODE(AND), /* A, B, C | R(A) <- RK(B) & RK(C) */ -OPCODE(OR), /* A, B, C | R(A) <- RK(B) | RK(C) */ -OPCODE(XOR), /* A, B, C | R(A) <- RK(B) ^ RK(C) */ -OPCODE(SHL), /* A, B, C | R(A) <- RK(B) << RK(C) */ -OPCODE(SHR), /* A, B, C | R(A) <- RK(B) >> RK(C) */ -OPCODE(CONNECT), /* A, B, C | R(A) <- connect(RK(B), RK(C)) */ -OPCODE(NEG), /* A, B | R(A) <- -RK(B) */ -OPCODE(FLIP), /* A, B | R(A) <- ~RK(B) */ -OPCODE(LDNIL), /* A | R(A) <- nil */ -OPCODE(LDBOOL), /* A, B, C | R(A) <- cast_bool(B), if(C): pc++ */ -OPCODE(LDINT), /* A, sBx | R(A) <- sBx */ -OPCODE(LDCONST), /* A, Bx | R(A) <- K(Bx) */ -OPCODE(MOVE), /* A, B, C | R(A) <- RK(B) */ -OPCODE(GETGBL), /* A, Bx | R(A) <- GLOBAL(Bx) */ -OPCODE(SETGBL), /* A, Bx | R(A) -> GLOBAL(Bx) */ -OPCODE(GETUPV), /* A, Bx | R(A) <- UPVALUE(Bx)*/ -OPCODE(SETUPV), /* A, Bx | R(A) -> UPVALUE(Bx)*/ -OPCODE(JMP), /* sBx | pc <- pc + sBx */ -OPCODE(JMPT), /* A, sBx | if(R(A)): pc <- pc + sBx */ -OPCODE(JMPF), /* A, sBx | if(not R(A)): pc <- pc + sBx */ -OPCODE(CALL), /* A, B | CALL(R(A), B) */ -OPCODE(RET), /* A, B | if (R(A)) R(-1) <- RK(B) else R(-1) <- nil */ -OPCODE(CLOSURE), /* A, Bx | R(A) <- CLOSURE(proto_table[Bx])*/ -OPCODE(GETMBR), /* A, B, C | R(A) <- RK(B).RK(C) */ -OPCODE(GETMET), /* A, B, C | R(A) <- RK(B).RK(C), R(A+1) <- RK(B) */ -OPCODE(SETMBR), /* A, B, C | R(A).RK(B) <- RK(C) */ -OPCODE(GETIDX), /* A, B, C | R(A) <- RK(B)[RK(C)] */ -OPCODE(SETIDX), /* A, B, C | R(A)[RK(B)] <- RK(C) */ -OPCODE(SETSUPER), /* A, B | class:R(A) set super with class:RK(B) */ -OPCODE(CLOSE), /* A | close upvalues */ -OPCODE(IMPORT), /* A, B, C | IF (A == C) import module name as RK(B) to RK(A), ELSE from module RK(C) import name as RK(B) to RK(A) */ -OPCODE(EXBLK), /* A, Bx | ... */ -OPCODE(CATCH), /* A, B, C | ... */ -OPCODE(RAISE), /* A, B, C | RAISE(B,C) B is code, C is description. A==0 only B provided, A==1 B and C are provided, A==2 rethrow with both parameters already on stack */ -OPCODE(CLASS), /* Bx | init class in K[Bx] */ -OPCODE(GETNGBL), /* A, B | R(A) <- GLOBAL[RK(B)] by name */ -OPCODE(SETNGBL) /* A, B | R(A) -> GLOBAL[RK(B)] by name */ diff --git a/lib/libesp32/Berry/src/be_oslib.c b/lib/libesp32/Berry/src/be_oslib.c deleted file mode 100644 index 1d4f029c29e7..000000000000 --- a/lib/libesp32/Berry/src/be_oslib.c +++ /dev/null @@ -1,271 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_strlib.h" -#include "be_mem.h" -#include "be_sys.h" -#include -#include - -#define FNAME_BUF_SIZE 512 - -#if BE_USE_OS_MODULE - -#if !BE_USE_FILE_SYSTEM - #error the dependent macro BE_USE_FILE_SYSTEM must be enabled -#endif - -static int m_getcwd(bvm *vm) -{ - char *buf = be_malloc(vm, FNAME_BUF_SIZE); - if (be_getcwd(buf, FNAME_BUF_SIZE)) { - be_pushstring(vm, buf); - } else { - be_pushstring(vm, ""); - } - be_free(vm, buf, FNAME_BUF_SIZE); - be_return(vm); -} - -static int m_chdir(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - int res = be_chdir(be_tostring(vm, 1)); - be_pushbool(vm, res == 0); - } - be_return(vm); -} - -static int m_mkdir(bvm *vm) -{ - int res = 1; - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - res = be_mkdir(be_tostring(vm, 1)); - } - be_pushbool(vm, res == 0); - be_return(vm); -} - -static int m_remove(bvm *vm) -{ - int res = 1; - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - res = be_unlink(be_tostring(vm, 1)); - } - be_pushbool(vm, res == 0); - be_return(vm); -} - -static int m_listdir(bvm *vm) -{ - int res; - bdirinfo info; - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - res = be_dirfirst(&info, be_tostring(vm, 1)); - } else { - res = be_dirfirst(&info, "."); - } - be_newobject(vm, "list"); - while (res == 0) { - const char *fn = info.name; - if (strcmp(fn, ".") && strcmp(fn, "..")) { - be_pushstring(vm, fn); - be_data_push(vm, -2); - be_pop(vm, 1); - } - res = be_dirnext(&info); - } - be_dirclose(&info); - be_pop(vm, 1); - be_return(vm); -} - -static int m_system(bvm *vm) -{ - int res = -1, i, argc = be_top(vm); - if (argc > 0) { - be_tostring(vm, 1); - be_pushstring(vm, " "); - for (i = 2; i <= argc; ++i) { - be_strconcat(vm, 1); /* add " " */ - be_tostring(vm, i); - be_pushvalue(vm, i); - be_strconcat(vm, 1); /* concat arg */ - be_pop(vm, 1); - } - be_pop(vm, argc); - res = system(be_tostring(vm, 1)); - } - be_pushint(vm, res); - be_return(vm); -} - -static int m_exit(bvm *vm) -{ - int status = 0; - if (be_top(vm)) { - if (be_isint(vm, 1)) { - status = be_toindex(vm, 1); /* get the exit code */ - } else if (be_isbool(vm, 1)) { - status = be_tobool(vm, 1) - 1; /* true: 0, false: -1 */ - } else { - status = -1; - } - } - be_exit(vm, status); - be_return_nil(vm); -} - -static int m_path_isdir(bvm *vm) -{ - const char *path = NULL; - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - path = be_tostring(vm, 1); - } - be_pushbool(vm, be_isdir(path)); - be_return(vm); -} - -static int m_path_isfile(bvm *vm) -{ - const char *path = NULL; - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - path = be_tostring(vm, 1); - } - be_pushbool(vm, be_isfile(path)); - be_return(vm); -} - -static int m_path_split(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - const char *path = be_tostring(vm, 1); - const char *split = be_splitpath(path); - size_t len = split - path; - if (split > path + 1 && split[-1] == '/') { - const char *p = split - 1; - for (; p >= path && *p == '/'; --p); - if (p >= path) { - len = p - path + 1; - } - } - be_getbuiltin(vm, "list"); - be_pushnstring(vm, path, len); - be_pushstring(vm, split); - be_call(vm, 2); - be_return(vm); - } - be_return_nil(vm); -} - -static int m_path_splitext(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - const char *path = be_tostring(vm, 1); - const char *split = be_splitname(path); - be_getbuiltin(vm, "list"); - be_pushnstring(vm, path, split - path); - be_pushstring(vm, split); - be_call(vm, 2); - be_return(vm); - } - be_return_nil(vm); -} - -static int m_path_exists(bvm *vm) -{ - const char *path = NULL; - if (be_top(vm) >= 1 && be_isstring(vm, 1)) { - path = be_tostring(vm, 1); - } - be_pushbool(vm, be_isexist(path)); - be_return(vm); -} - -static int m_path_join(bvm *vm) -{ - char *buf, *p; - int i, len = 0, argc = be_top(vm); - for (i = 1; i <= argc; ++i) { - if (be_isstring(vm, i)) { - len += be_strlen(vm, i) + 1; - } else { - be_raise(vm, "type_error", "arguments must be string"); - } - } - buf = p = be_malloc(vm, (size_t)len + 1); - for (i = 1; i <= argc; ++i) { - int l = be_strlen(vm, i); - const char *s = be_tostring(vm, i); - if (s[0] == '/') { - p = buf; - } - strcpy(p, s); - p += l; - if (l && s[l - 1] != '/' && i != argc) { - *p++ = '/'; - } - } - be_pushnstring(vm, buf, p - buf); - be_free(vm, buf, (size_t)len + 1); - be_return(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(path) { - be_native_module_function("isdir", m_path_isdir), - be_native_module_function("isfile", m_path_isfile), - be_native_module_function("exists", m_path_exists), - be_native_module_function("split", m_path_split), - be_native_module_function("splitext", m_path_splitext), - be_native_module_function("join", m_path_join) -}; - -static be_define_native_module(path, NULL); - -be_native_module_attr_table(os) { - be_native_module_function("getcwd", m_getcwd), - be_native_module_function("chdir", m_chdir), - be_native_module_function("mkdir", m_mkdir), - be_native_module_function("remove", m_remove), - be_native_module_function("listdir", m_listdir), - be_native_module_function("system", m_system), - be_native_module_function("exit", m_exit), - be_native_module_module("path", be_native_module(path)) -}; - -be_define_native_module(os, NULL); -#else -/* @const_object_info_begin -module path (scope: local, file: os_path, depend: BE_USE_OS_MODULE) { - isdir, func(m_path_isdir) - isfile, func(m_path_isfile) - exists, func(m_path_exists) - split, func(m_path_split) - splitext, func(m_path_splitext) - join, func(m_path_join) -} -@const_object_info_end */ -#include "../generate/be_fixed_os_path.h" - -/* @const_object_info_begin -module os (scope: global, depend: BE_USE_OS_MODULE) { - getcwd, func(m_getcwd) - chdir, func(m_chdir) - mkdir, func(m_mkdir) - remove, func(m_remove) - listdir, func(m_listdir) - system, func(m_system) - exit, func(m_exit) - path, module(m_libpath) -} -@const_object_info_end */ -#include "../generate/be_fixed_os.h" -#endif - -#endif /* BE_USE_OS_MODULE */ diff --git a/lib/libesp32/Berry/src/be_parser.c b/lib/libesp32/Berry/src/be_parser.c deleted file mode 100644 index 9737cdf81cc7..000000000000 --- a/lib/libesp32/Berry/src/be_parser.c +++ /dev/null @@ -1,1838 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_parser.h" -#include "be_lexer.h" -#include "be_vector.h" -#include "be_mem.h" -#include "be_vm.h" -#include "be_map.h" -#include "be_list.h" -#include "be_var.h" -#include "be_code.h" -#include "be_string.h" -#include "be_func.h" -#include "be_class.h" -#include "be_decoder.h" -#include "be_exec.h" -#include - -#define OP_NOT_BINARY TokenNone -#define OP_NOT_UNARY TokenNone -#define OP_NOT_ASSIGN TokenNone -#define UNARY_OP_PRIO 3 -#define ASSIGN_OP_PRIO 16 - -#define FUNC_METHOD 1 -#define FUNC_ANONYMOUS 2 -#define FUNC_STATIC 4 - -#if BE_INTGER_TYPE == 0 /* int */ - #define M_IMAX INT_MAX - #define M_IMIN INT_MIN -#elif BE_INTGER_TYPE == 1 /* long */ - #define M_IMAX LONG_MAX - #define M_IMIN LONG_MIN -#else /* int64_t (long long) */ - #define M_IMAX LLONG_MAX - #define M_IMIN LLONG_MIN -#endif - -/* get binary operator priority */ -#define binary_op_prio(op) (binary_op_prio_tab[cast_int(op) - OptAdd]) - -#define scan_next_token(parser) (be_lexer_scan_next(&(parser)->lexer)) -#define next_token(parser) ((parser)->lexer.token) -#define next_type(parser) (next_token(parser).type) -#define max(a, b) ((a) > (b) ? (a) : (b)) -#define token2str(parser) be_token2str((parser)->vm, &next_token(parser)) -#define funcname(parser) ((parser)->islocal ? "loader" : "main") - -#define upval_index(v) ((v) & 0xFF) -#define upval_target(v) ((bbyte)(((v) >> 8) & 0xFF)) -#define upval_instack(v) ((bbyte)(((v) >> 16) != 0)) -#define upval_desc(i, t, s) (((i) & 0xFF) | (((t) & 0xFF) << 8) \ - | (((s) != 0) << 16)) - -#define match_id(parser, s) ((s) = _match_id(parser)) - -#define parser_newstr(p, str) be_lexer_newstr(&(p)->lexer, (str)) - -#define parser_error(p, msg) be_lexerror(&(p)->lexer, msg) - -#define push_error(parser, ...) \ - parser_error(parser, be_pushfstring(parser->vm, __VA_ARGS__)) - -typedef struct { - blexer lexer; - bvm *vm; - bfuncinfo *finfo; - bclosure *cl; - bbyte islocal; -} bparser; - -#if BE_USE_SCRIPT_COMPILER - -static void stmtlist(bparser *parser); -static void block(bparser *parser, int type); -static void expr(bparser *parser, bexpdesc *e); -static void walrus_expr(bparser *parser, bexpdesc *e); -static void sub_expr(bparser *parser, bexpdesc *e, int prio); - -static const bbyte binary_op_prio_tab[] = { - 5, 5, 4, 4, 4, /* + - * / % */ - 11, 11, 12, 12, 11, 11, /* < <= == != > >= */ - 7, 9, 8, 6, 6, 10, 13, 14 /* & | ^ << >> .. && || */ -}; - -static void match_token(bparser *parser, btokentype type) -{ - if (next_type(parser) != type) { /* error when token is no match */ - btoken *token = &next_token(parser); - const char *s1 = be_tokentype2str(type); - const char *s2 = be_token2str(parser->vm, token); - push_error(parser, "expected '%s' before '%s'", s1, s2); - } - scan_next_token(parser); /* skip this token */ -} - -/* Check that the next token is not of type `type` */ -/* or raise an exception */ -static void match_notoken(bparser *parser, btokentype type) -{ - if (next_type(parser) == type) { /* error when token is match */ - push_error(parser, - "expected statement before '%s'", token2str(parser)); - } -} - -/* check that if the expdesc is a symbol, it is a valid one or raise an exception */ -static void check_symbol(bparser *parser, bexpdesc *e) -{ - if (e->type == ETVOID && e->v.s == NULL) { /* error when token is not a symbol */ - push_error(parser, - "unexpected symbol near '%s'", token2str(parser)); - } -} - -/* check that the value in `e` is valid for a variable, i.e. contains a value or a valid symbol */ -static void check_var(bparser *parser, bexpdesc *e) -{ - check_symbol(parser, e); /* check the token is a symbol */ - if (e->type == ETVOID) { /* error when symbol is undefined */ - int line = parser->lexer.linenumber; - parser->lexer.linenumber = parser->lexer.lastline; - push_error(parser, - "'%s' undeclared (first use in this function)", str(e->v.s)); - parser->lexer.linenumber = line; - } -} - -static int match_skip(bparser *parser, btokentype type) -{ - if (next_type(parser) == type) { /* match */ - scan_next_token(parser); /* skip this token */ - return btrue; - } - return bfalse; -} - -static bstring* _match_id(bparser *parser) -{ - if (next_type(parser) == TokenId) { - bstring *str = next_token(parser).u.s; - scan_next_token(parser); /* skip ID */ - return str; - } - return NULL; -} - -#if BE_DEBUG_VAR_INFO - -void begin_varinfo(bparser *parser, bstring *name) -{ - bvarinfo *var; - bfuncinfo *finfo = parser->finfo; - be_vector_push_c(parser->vm, &finfo->varvec, NULL); - var = be_vector_end(&finfo->varvec); - var->name = name; - var->beginpc = finfo->pc; - var->endpc = 0; /* */ - finfo->proto->varinfo = be_vector_data(&finfo->varvec); - finfo->proto->nvarinfo = be_vector_capacity(&finfo->varvec); -} - -void end_varinfo(bparser *parser, int beginpc) -{ - bfuncinfo *finfo = parser->finfo; - bblockinfo *binfo = finfo->binfo; - bvarinfo *it = be_vector_data(&finfo->varvec); - bvarinfo *end = be_vector_end(&finfo->varvec); - if (beginpc == -1) /* use block->beginpc by default */ - beginpc = binfo->beginpc; - /* skip the variable of the previous blocks */ - for (; (it <= end) && (it->beginpc < beginpc); ++it); - for (; it <= end; ++it) { - if (!it->endpc) /* write to endpc only once */ - it->endpc = finfo->pc; - } -} - -#else - -#define begin_varinfo(parser, name) -#define end_varinfo(parser, beginpc) (void)(beginpc) - -#endif - -/* Initialize bblockinfo structure */ -static void begin_block(bfuncinfo *finfo, bblockinfo *binfo, int type) -{ - binfo->prev = finfo->binfo; /* save previous block */ - finfo->binfo = binfo; /* tell parser this is the current block */ - binfo->type = (bbyte)type; - binfo->hasupval = 0; - binfo->sideeffect = 0; - binfo->lastjmp = 0; - binfo->beginpc = finfo->pc; /* set starting pc for this block */ - binfo->nactlocals = (bbyte)be_list_count(finfo->local); /* count number of local variables in previous block */ - if (type & BLOCK_LOOP) { - binfo->breaklist = NO_JUMP; - binfo->continuelist = NO_JUMP; - } -} - -static void end_block_ex(bparser *parser, int beginpc) -{ - bfuncinfo *finfo = parser->finfo; - bblockinfo *binfo = finfo->binfo; - be_code_close(finfo, 0); /* close upvalues */ - if (binfo->type & BLOCK_LOOP) { - be_code_jumpto(finfo, binfo->beginpc); - be_code_patchjump(finfo, binfo->breaklist); - be_code_patchlist(finfo, binfo->continuelist, binfo->beginpc); - } - end_varinfo(parser, beginpc); - be_list_resize(parser->vm, finfo->local, binfo->nactlocals); /* remove local variables from this block, they are now out of scope */ - finfo->freereg = binfo->nactlocals; /* adjust first free register accordingly */ - finfo->binfo = binfo->prev; /* restore previous block */ -} - -static void end_block(bparser *parser) -{ - end_block_ex(parser, -1); -} - -#if BE_DEBUG_SOURCE_FILE -/* Return the name of the source for this parser, could be `string`, - `stdin` or the name of the current function */ -static bstring* parser_source(bparser *parser) -{ - if (parser->finfo) { - return parser->finfo->proto->source; - } - return be_newstr(parser->vm, parser->lexer.fname); -} -#endif - -/* Initialize a function block and create a new `bprotoˋ */ -static void begin_func(bparser *parser, bfuncinfo *finfo, bblockinfo *binfo) -{ - bvm *vm = parser->vm; - bproto *proto = be_newproto(vm); - var_setproto(vm->top, proto); - be_stackpush(vm); - be_vector_init(vm, &finfo->code, sizeof(binstruction)); /* vector for code, vectors are not gced */ - proto->code = be_vector_data(&finfo->code); - proto->codesize = be_vector_capacity(&finfo->code); - be_vector_init(vm, &finfo->kvec, sizeof(bvalue)); /* vector for constants */ - proto->ktab = be_vector_data(&finfo->kvec); - proto->nconst = be_vector_capacity(&finfo->kvec); - be_vector_init(vm, &finfo->pvec, sizeof(bproto*)); /* vector for subprotos */ - proto->ptab = be_vector_data(&finfo->pvec); - proto->nproto = be_vector_capacity(&finfo->pvec); -#if BE_DEBUG_SOURCE_FILE - proto->source = parser_source(parser); /* keep a copy of source for function */ -#endif - finfo->local = be_list_new(vm); /* list for local variables */ - var_setlist(vm->top, finfo->local); /* push list of local variables on the stack (avoid gc) */ - be_stackpush(vm); - finfo->upval = be_map_new(vm); /* push a map for upvals on stack */ - var_setmap(vm->top, finfo->upval); - be_stackpush(vm); - finfo->prev = parser->finfo; /* init finfo */ - finfo->lexer = &parser->lexer; - finfo->proto = proto; - finfo->freereg = 0; - finfo->binfo = NULL; - finfo->pc = 0; - finfo->flags = 0; - parser->finfo = finfo; -#if BE_DEBUG_RUNTIME_INFO - be_vector_init(vm, &finfo->linevec, sizeof(blineinfo)); - proto->lineinfo = be_vector_data(&finfo->linevec); - proto->nlineinfo = be_vector_capacity(&finfo->linevec); -#endif -#if BE_DEBUG_VAR_INFO - be_vector_init(vm, &finfo->varvec, sizeof(bvarinfo)); - proto->varinfo = be_vector_data(&finfo->varvec); - proto->nvarinfo = be_vector_capacity(&finfo->varvec); -#endif - begin_block(finfo, binfo, 0); -} - -/* compute the upval structure */ -static void setupvals(bfuncinfo *finfo) -{ - bproto *proto = finfo->proto; - int nupvals = be_map_count(finfo->upval); - if (nupvals) { - bmapnode *node; - bmap *map = finfo->upval; - bmapiter iter = be_map_iter(); - bupvaldesc *upvals = be_malloc( - finfo->lexer->vm, sizeof(bupvaldesc) * nupvals); - while ((node = be_map_next(map, &iter)) != NULL) { - uint32_t v = (uint32_t)var_toint(&node->value); - bupvaldesc *uv = upvals + upval_index(v); - uv->idx = upval_target(v); - uv->instack = upval_instack(v); -#if BE_DEBUG_VAR_INFO - uv->name = var_tostr(&node->key); -#endif - } - proto->upvals = upvals; - proto->nupvals = (bbyte)nupvals; - } -} - -/* Function is complete, finalize bproto */ -static void end_func(bparser *parser) -{ - bvm *vm = parser->vm; - bfuncinfo *finfo = parser->finfo; - bproto *proto = finfo->proto; - - be_code_ret(finfo, NULL); /* append a return to last code */ - end_block(parser); /* close block */ - setupvals(finfo); /* close upvals */ - proto->code = be_vector_release(vm, &finfo->code); /* compact all vectors and return NULL if empty */ - proto->codesize = finfo->pc; - proto->ktab = be_vector_release(vm, &finfo->kvec); - proto->nconst = be_vector_count(&finfo->kvec); - proto->nproto = be_vector_count(&finfo->pvec); - proto->ptab = be_vector_release(vm, &finfo->pvec); -#if BE_USE_MEM_ALIGNED - proto->code = be_move_to_aligned(vm, proto->code, proto->codesize * sizeof(binstruction)); /* move `code` to 4-bytes aligned memory region */ - proto->ktab = be_move_to_aligned(vm, proto->ktab, proto->nconst * sizeof(bvalue)); /* move `ktab` to 4-bytes aligned memory region */ -#endif /* BE_USE_MEM_ALIGNED */ -#if BE_DEBUG_RUNTIME_INFO - proto->lineinfo = be_vector_release(vm, &finfo->linevec); /* move `lineinfo` to 4-bytes aligned memory region */ - proto->nlineinfo = be_vector_count(&finfo->linevec); -#if BE_USE_MEM_ALIGNED - proto->lineinfo = be_move_to_aligned(vm, proto->lineinfo, proto->nlineinfo * sizeof(blineinfo)); -#endif /* BE_USE_MEM_ALIGNED */ -#endif /* BE_DEBUG_RUNTIME_INFO */ -#if BE_DEBUG_VAR_INFO - proto->varinfo = be_vector_release(vm, &finfo->varvec); - proto->nvarinfo = be_vector_count(&finfo->varvec); -#endif - parser->finfo = parser->finfo->prev; /* restore previous `finfo` */ - be_stackpop(vm, 2); /* pop upval and local */ -} - -/* is the next token a binary operator? If yes return the operator or `OP_NOT_BINARY` */ -static btokentype get_binop(bparser *parser) -{ - btokentype op = next_type(parser); - if (op >= OptAdd && op <= OptOr) { - return op; - } - return OP_NOT_BINARY; -} - -/* is the next token a unary operator? If yes return the operator or `OP_NOT_BINARY` */ -/* operator 'negative' 'not' and 'flip' */ -static btokentype get_unary_op(bparser *parser) -{ - btokentype op = next_type(parser); - if (op == OptSub || op == OptNot || op == OptFlip) { - return op; /* operator 'negative' 'not' and 'flip' */ - } - return OP_NOT_UNARY; -} - -/* is the next token an assignment operator? If yes return the operator or `OP_NOT_BINARY` */ -/* `=`, `+=`, ... `>>=` */ -static btokentype get_assign_op(bparser *parser) -{ - btokentype op = next_type(parser); - if ((op >= OptAssign && op <= OptRsfAssign) || op == OptWalrus) { - return op; - } - return OP_NOT_ASSIGN; -} - -/* Initialize bexpdesc structure with specific type and value as int */ -static void init_exp(bexpdesc *e, exptype_t type, bint i) -{ - e->type = (bbyte)type; - e->t = NO_JUMP; - e->f = NO_JUMP; - e->not = 0; - e->v.s = NULL; - e->v.i = i; -} - -/* find local variable by name, starting at index `begin` */ -/* linear search, returns -1 if not found */ -static int find_localvar(bfuncinfo *finfo, bstring *s, int begin) -{ - int i, count = be_list_count(finfo->local); - bvalue *var = be_list_data(finfo->local); - for (i = count - 1; i >= begin; --i) { - if (be_eqstr(var[i].v.s, s)) { - return i; - } - } - return -1; /* not found */ -} - -/* create a new local variable by name, or return the current register if already exists */ -/* returns the Reg number for the variable */ -/* If STRICT, we don't allow a var to hide a var from outer scope */ -/* We don't allow the same var to be defined twice in same scope */ -static int new_localvar(bparser *parser, bstring *name) -{ - bfuncinfo *finfo = parser->finfo; - int reg = find_localvar(finfo, name, finfo->binfo->nactlocals); /* look if already exists skipping the local variables from upper blocks */ - /* 'strict': raise an exception if the local variable shadows another local variable */ - if (reg == -1) { - bvalue *var; - if (comp_is_strict(parser->vm)) { - if (find_localvar(finfo, name, 0) >= 0 && str(name)[0] != '.') { /* we do accept nested redifinition of internal variables starting with '.' */ - push_error(parser, "strict: redefinition of '%s' from outer scope", str(name)); - } - } - reg = be_list_count(finfo->local); /* new local index */ - var = be_list_push(parser->vm, finfo->local, NULL); - var_setstr(var, name); - if (reg >= finfo->freereg) { - be_code_allocregs(finfo, 1); /* use a register */ - } - begin_varinfo(parser, name); - } else { - push_error(parser, "redefinition of '%s'", str(name)); - } - return reg; -} - -/* Find upval by name, if found return its index number, or -1 */ -static int find_upval(bfuncinfo *finfo, bstring *s) -{ - bvm *vm = finfo->lexer->vm; - bvalue *desc = be_map_findstr(vm, finfo->upval, s); - if (desc) { - return upval_index(desc->v.i); - } - return -1; -} - -/* Recursively search for upper blocks that are referenced in upvals */ -/* and mark them with `hasupval` */ -static void mark_upval(bfuncinfo *finfo, int level) -{ - bblockinfo *binfo = finfo->prev->binfo; - while (binfo->nactlocals > level) { - binfo = binfo->prev; - } - binfo->hasupval = 1; -} - -static int new_upval(bvm *vm, bfuncinfo *finfo, bstring *name, bexpdesc *var) -{ - int index; - bvalue *desc; - int target = var->v.idx; - int instack = var->type == ETLOCAL; - if (instack) { /* mark upvalue's block */ - mark_upval(finfo, target); - } - index = be_map_count(finfo->upval); - if (index >= 255) { - be_lexerror(finfo->lexer, be_pushfstring(vm, - "too many upvalues (in '%s')", str(name))); - } - desc = be_map_insertstr(vm, finfo->upval, name, NULL); - var_setint(desc, upval_desc(index, target, instack)); - return index; -} - -/* create a new variable in currenr context as name, and create expdesc for it */ -/* If within a block, create as local, otherwise as global */ -static void new_var(bparser *parser, bstring *name, bexpdesc *var) -{ - bfuncinfo *finfo = parser->finfo; - if (comp_is_strict(parser->vm)) { - /* check if we are masking a builtin */ - if (be_builtin_find(parser->vm, name) >= 0) { - push_error(parser, "strict: redefinition of builtin '%s'", str(name)); - } - } - if (finfo->prev || finfo->binfo->prev || parser->islocal) { - init_exp(var, ETLOCAL, 0); - var->v.idx = new_localvar(parser, name); /* if local, contains the index in current local var list */ - } else { - init_exp(var, ETGLOBAL, 0); - var->v.idx = be_global_new(parser->vm, name); - if (var->v.idx > (int)IBx_MASK) { - push_error(parser, - "too many global variables (in '%s')", str(name)); - } - if (comp_is_named_gbl(parser->vm)) { - /* change to ETNGLBAL */ - bexpdesc key; - init_exp(&key, ETSTRING, 0); - key.v.s = name; - init_exp(var, ETNGLOBAL, 0); - var->v.idx = be_code_nglobal(parser->finfo, &key); - } - } -} - -static int singlevaraux(bvm *vm, bfuncinfo *finfo, bstring *s, bexpdesc *var) -{ - if (finfo == NULL) { - return ETVOID; - } else { - int idx = find_localvar(finfo, s, 0); - if (idx >= 0) { /* local variable */ - init_exp(var, ETLOCAL, 0); - var->v.idx = idx; - return ETLOCAL; - } else { - idx = find_upval(finfo, s); - if (idx < 0) { - /* find the previous scope */ - int res = singlevaraux(vm, finfo->prev, s, var); - if (res == ETUPVAL || res == ETLOCAL) { - idx = new_upval(vm, finfo, s, var); /* new upvalue */ - } else { - idx = be_global_find(vm, s); - if (idx >= 0) { - if (idx < be_builtin_count(vm)) { - return ETGLOBAL; /* global variable */ - } else { - return comp_is_named_gbl(vm) ? ETNGLOBAL : ETGLOBAL; /* global variable */ - } - } else { - return ETVOID; /* unknow (new variable or error) */ - } - } - } - init_exp(var, ETUPVAL, idx); - return ETUPVAL; - } - } -} - -/* get variable from next toden as name */ -/* and create an expdesc from it */ -/* can be new, global, named global, upval */ -static void singlevar(bparser *parser, bexpdesc *var) -{ - bexpdesc key; - bstring *varname = next_token(parser).u.s; - int type = singlevaraux(parser->vm, parser->finfo, varname, var); - switch (type) { - case ETVOID: - init_exp(var, ETVOID, 0); - var->v.s = varname; - break; - case ETGLOBAL: - init_exp(var, ETGLOBAL, 0); - var->v.idx = be_global_find(parser->vm, varname); - break; - case ETNGLOBAL: - init_exp(&key, ETSTRING, 0); - key.v.s = varname; - init_exp(var, ETNGLOBAL, 0); - var->v.idx = be_code_nglobal(parser->finfo, &key); - break; - default: - break; - } -} - -/* parse a vararg argument in the form `def f(a, *b) end` */ -/* Munch the '*', read the token, create variable and declare the function as vararg */ -static void func_vararg(bparser *parser) { - bexpdesc v; - bstring *str; - match_token(parser, OptMul); /* skip '*' */ - str = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - new_var(parser, str, &v); /* new variable */ - parser->finfo->proto->varg |= BE_VA_VARARG; /* set varg flag */ -} - -/* Parse function or method definition variable list */ -/* Create an implicit local variable for each argument starting at R0 */ -/* Update function proto argc to the expected number or arguments */ -/* Raise an exception if multiple arguments have the same name */ -/* New: vararg support */ -static void func_varlist(bparser *parser) -{ - bexpdesc v; - bstring *str; - /* '(' [ ID {',' ID}] ')' or */ - /* '(' '*' ID ')' or */ - /* '(' [ ID {',' ID}] ',' '*' ID ')' */ - match_token(parser, OptLBK); /* skip '(' */ - if (next_type(parser) == OptMul) { - func_vararg(parser); - } else if (match_id(parser, str) != NULL) { - new_var(parser, str, &v); /* new variable */ - while (match_skip(parser, OptComma)) { /* ',' */ - if (next_type(parser) == OptMul) { - func_vararg(parser); - break; - } else { - str = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - /* new local variable */ - new_var(parser, str, &v); - } - } - } - match_token(parser, OptRBK); /* skip ')' */ - parser->finfo->proto->argc = parser->finfo->freereg; -} - -/* Parse a function includind arg list and body */ -/* Given name and type (function or method) */ -/* Returns `bproto` object */ -static bproto* funcbody(bparser *parser, bstring *name, bclass *c, int type) -{ - bfuncinfo finfo; - bblockinfo binfo; - - /* '(' varlist ')' block 'end' */ - begin_func(parser, &finfo, &binfo); /* init new function context */ - finfo.proto->name = name; - if (type & FUNC_METHOD) { /* If method, add an implicit first argument `self` */ - new_localvar(parser, parser_newstr(parser, "self")); - finfo.proto->varg |= BE_VA_METHOD; - } - func_varlist(parser); /* parse arg list */ - if ((type & FUNC_STATIC) && (c != NULL)) { /* If static method, add an implicit local variable `_class` */ - bexpdesc e1, e2; - new_var(parser, parser_newstr(parser, "_class"), &e1); /* new implicit variable '_class' */ - init_exp(&e2, ETCONST, 0); - be_code_implicit_class(parser->finfo, &e2, c); - be_code_setvar(parser->finfo, &e1, &e2, bfalse); - finfo.proto->varg |= BE_VA_STATICMETHOD; - } - stmtlist(parser); /* parse statement without final `end` */ - end_func(parser); /* close function context */ - match_token(parser, KeyEnd); /* skip 'end' */ - return finfo.proto; /* return fully constructed `bproto` */ -} - -/* anonymous function, build `bproto` object with name `_anonymous_` */ -/* and build a expdesc for the bproto */ -static void anon_func(bparser *parser, bexpdesc *e) -{ - bproto *proto; - bstring *name = parser_newstr(parser, "_anonymous_"); - /* 'def' ID '(' varlist ')' block 'end' */ - scan_next_token(parser); /* skip 'def' */ - proto = funcbody(parser, name, NULL, FUNC_ANONYMOUS); - init_exp(e, ETPROTO, be_code_proto(parser->finfo, proto)); - be_stackpop(parser->vm, 1); -} - -static void lambda_varlist(bparser *parser) -{ - bexpdesc v; - bstring *str; - /* [ID {',' ID}] | {ID}] */ - if (match_id(parser, str) != NULL) { - bbool comma; - new_var(parser, str, &v); /* new variable */ - comma = next_type(parser) == OptComma; - while (next_type(parser) != OptArrow) { - if (comma) { - match_token(parser, OptComma); /* match and skip ',' */ - } - str = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - /* new local variable */ - new_var(parser, str, &v); - } - } - match_token(parser, OptArrow); /* skip '->' */ - parser->finfo->proto->argc = parser->finfo->freereg; -} - -/* lambda expression */ -static void lambda_expr(bparser *parser, bexpdesc *e) -{ - bexpdesc e1; - bfuncinfo finfo; - bblockinfo binfo; - bstring *name = parser_newstr(parser, ""); - /* '/' ID {[',' ID]} '->' expr */ - scan_next_token(parser); /* skip '/' */ - begin_func(parser, &finfo, &binfo); - finfo.proto->name = name; - lambda_varlist(parser); - expr(parser, &e1); - check_var(parser, &e1); - be_code_ret(parser->finfo, &e1); - end_func(parser); - init_exp(e, ETPROTO, be_code_proto(parser->finfo, finfo.proto)); - be_stackpop(parser->vm, 1); -} - -/* Instanciate a builtin type by name */ -/* Allocates a new register for the value, and call empty constructor */ -/* Is allocated as LOCAL and must be changed to REG when completed */ -static void new_primtype(bparser *parser, const char *type, bexpdesc *e) -{ - int idx; - bvm *vm = parser->vm; - bfuncinfo *finfo = parser->finfo; - - scan_next_token(parser); - idx = be_builtin_find(vm, parser_newstr(parser, type)); - init_exp(e, ETGLOBAL, idx); - idx = be_code_nextreg(finfo, e); - be_code_call(finfo, idx, 0); - e->type = ETLOCAL; /* declare as local, will be changed to ETREG when completely initialized */ -} - -/* Parse next member within a list */ -/* `l` contains the current list. The expr is evaluated and added to the list */ -static void list_nextmember(bparser *parser, bexpdesc *l) -{ - bexpdesc e, v = *l; - bfuncinfo *finfo = parser->finfo; - expr(parser, &e); /* value */ - check_var(parser, &e); /* check that we don´t have an unknown symbol */ - be_code_binop(finfo, OptConnect, &v, &e, -1); /* add it to list with CONNECT */ - be_code_freeregs(finfo, 1); /* since left arg is LOCAL, an ETREG was allocated. Free it */ -} - -static void map_nextmember(bparser *parser, bexpdesc *l) -{ - bexpdesc e, v = *l; - bfuncinfo *finfo = parser->finfo; - expr(parser, &e); /* key */ - check_var(parser, &e); /* check if value is valid */ - be_code_index(finfo, &v, &e); /* package as `v` as INDEX suffix for value `e` */ - match_token(parser, OptColon); /* ':' */ - expr(parser, &e); /* value in `e` */ - check_var(parser, &e); /* check if value is correct */ - be_code_setvar(finfo, &v, &e, bfalse); /* set suffi INDEX value to e */ -} - -static void list_expr(bparser *parser, bexpdesc *e) -{ - /* '[' {expr ','} [expr] ']' */ - new_primtype(parser, "list", e); /* new list, created as LOCAL first */ - while (next_type(parser) != OptRSB) { - list_nextmember(parser, e); - if (!match_skip(parser, OptComma)) { /* ',' */ - break; - } - } - e->type = ETREG; /* then turned to REG */ - match_token(parser, OptRSB); /* skip ']' */ -} - -static void map_expr(bparser *parser, bexpdesc *e) -{ - /* '{' {expr ':' expr ','} [expr ':' expr] '}' */ - new_primtype(parser, "map", e); /* new map */ - while (next_type(parser) != OptRBR) { - map_nextmember(parser, e); - if (!match_skip(parser, OptComma)) { /* ',' */ - break; - } - } - e->type = ETREG; - match_token(parser, OptRBR); /* skip '}' */ -} - -/* push each argument as new reg and return number of args */ -/* TODO `e` is ignored by caller */ -static int exprlist(bparser *parser, bexpdesc *e) -{ - bfuncinfo *finfo = parser->finfo; - int n = 1; - /* expr { ',' expr } */ - expr(parser, e); /* parse expr */ - check_var(parser, e); /* check if valid */ - be_code_nextreg(finfo, e); /* move result to next reg */ - while (match_skip(parser, OptComma)) { /* ',' */ - expr(parser, e); - check_var(parser, e); - be_code_nextreg(finfo, e); - ++n; - } - return n; -} - -/* parse call to method or function */ -/* `e` can be a member (method) or a register */ -/* On return, `e` is ETREG to the result of the call */ -static void call_expr(bparser *parser, bexpdesc *e) -{ - bexpdesc args; - bfuncinfo *finfo = parser->finfo; - int argc = 0, base; - int ismember = e->type == ETMEMBER; - - parser->finfo->binfo->sideeffect = 1; /* has side effect */ - /* func '(' [exprlist] ')' */ - check_var(parser, e); - /* code function index to next register */ - if (ismember) { - base = be_code_getmethod(finfo, e); - } else { - base = be_code_nextreg(finfo, e); /* allocate a new base reg if not at top already */ - } - /* base is always taken at top of freereg and allocates 1 reg for function and 2 regs for method */ - scan_next_token(parser); /* skip '(' */ - if (next_type(parser) != OptRBK) { /* if arg list is not empty */ - argc = exprlist(parser, &args); /* push each argument as new reg and return number of args */ - } - match_token(parser, OptRBK); /* skip ')' */ - argc += ismember; /* if method there is an additional implicit arg */ - be_code_call(finfo, base, argc); - if (e->type != ETREG) { - e->type = ETREG; - e->v.idx = base; - } -} - -/* Parse member expression */ -/* Generates an ETMEMBER object that is materialized later into GETMBR, GETMET or SETMBR */ -static void member_expr(bparser *parser, bexpdesc *e) -{ - bstring *str; - /* . ID */ - check_var(parser, e); - scan_next_token(parser); /* skip '.' */ - if (match_id(parser, str) != NULL) { - bexpdesc key; - init_exp(&key, ETSTRING, 0); - key.v.s = str; - be_code_member(parser->finfo, e, &key); - } else if (next_type(parser) == OptLBK) { - scan_next_token(parser); /* skip '(' */ - bexpdesc key; - expr(parser, &key); - check_var(parser, &key); - match_token(parser, OptRBK); /* skip ')' */ - be_code_member(parser->finfo, e, &key); - } else { - push_error(parser, "invalid syntax near '%s'", - be_token2str(parser->vm, &next_token(parser))); - } -} - -static void index_expr(bparser *parser, bexpdesc *e) -{ - bexpdesc e1; - /* [expr] */ - check_var(parser, e); - scan_next_token(parser); /* skip '[' */ - expr(parser, &e1); - check_var(parser, &e1); - be_code_index(parser->finfo, e, &e1); - match_token(parser, OptRSB); /* skip ']' */ -} - -static void simple_expr(bparser *parser, bexpdesc *e) -{ - switch (next_type(parser)) { - case TokenInteger: - init_exp(e, ETINT, next_token(parser).u.i); - break; - case TokenReal: - init_exp(e, ETREAL, 0); - e->v.r = next_token(parser).u.r; - break; - case TokenString: - init_exp(e, ETSTRING, 0); - e->v.s = next_token(parser).u.s; - break; - case TokenId: - singlevar(parser, e); - break; - case KeyTrue: - init_exp(e, ETBOOL, 1); - break; - case KeyFalse: - init_exp(e, ETBOOL, 0); - break; - case KeyNil: - init_exp(e, ETNIL, 0); - break; - default: /* unknow expr */ - return; - } - scan_next_token(parser); -} - -static void primary_expr(bparser *parser, bexpdesc *e) -{ - switch (next_type(parser)) { - case OptLBK: /* '(' expr ')' */ - scan_next_token(parser); /* skip '(' */ - expr(parser, e); - check_var(parser, e); - match_token(parser, OptRBK); /* skip ')' */ - break; - case OptLSB: /* list */ - list_expr(parser, e); - break; - case OptLBR: /* map */ - map_expr(parser, e); - break; - case KeyDef: /* anonymous function */ - anon_func(parser, e); - break; - case OptDiv: /* lambda expression */ - lambda_expr(parser, e); - break; - default: /* simple expr */ - simple_expr(parser, e); - break; - } -} - -static void suffix_expr(bparser *parser, bexpdesc *e) -{ - primary_expr(parser, e); - for (;;) { - switch (next_type(parser)) { - case OptLBK: /* '(' function call */ - call_expr(parser, e); - break; - case OptDot: /* '.' member */ - member_expr(parser, e); - break; - case OptLSB: /* '[' index */ - index_expr(parser, e); - break; - default: - return; - } - } -} - -static void suffix_alloc_reg(bparser *parser, bexpdesc *l) -{ - bfuncinfo *finfo = parser->finfo; - bbool is_suffix = l->type == ETINDEX || l->type == ETMEMBER; /* is suffix */ - bbool is_suffix_reg = l->v.ss.tt == ETREG || l->v.ss.tt == ETLOCAL || l->v.ss.tt == ETGLOBAL || l->v.ss.tt == ETNGLOBAL; /* if suffix, does it need a register */ - bbool is_global = l->type == ETGLOBAL || l->type == ETNGLOBAL; - bbool is_upval = l->type == ETUPVAL; - /* in the suffix expression, if the object is a temporary - * variable (l->v.ss.tt == ETREG), it needs to be cached. */ - if (is_global || is_upval || (is_suffix && is_suffix_reg)) { - be_code_allocregs(finfo, 1); - } -} - -/* compound assignment */ -static void compound_assign(bparser *parser, int op, bexpdesc *l, bexpdesc *r) -{ - int dst = -1; /* destination register in case of compound assignment */ - if (op != OptAssign) { /* check left variable */ - check_var(parser, l); - /* cache the register of the object when continuously assigning */ - dst = parser->finfo->freereg; - suffix_alloc_reg(parser, l); - } - expr(parser, r); /* right expression */ - check_var(parser, r); - if (op != OptAssign) { /* compound assignment */ - bexpdesc e = *l; - op = op < OptAndAssign ? op - OptAddAssign + OptAdd - : op - OptAndAssign + OptBitAnd; - be_code_binop(parser->finfo, op, &e, r, dst); /* coding operation */ - *r = e; - } -} - -/* check if we need to create a new local variable with this name to be assigned to */ -/* Returns true if it´s a new local variable */ -/* A new implicit local variable is created if no global has the same name (excluding builtins) */ -/* This means that you can override a builtin silently */ -/* This also means that a function cannot create a global, they must preexist or create with `global` module */ -static int check_newvar(bparser *parser, bexpdesc *e) -{ - if (e->type == ETGLOBAL) { - if (e->v.idx < be_builtin_count(parser->vm)) { - e->v.s = be_builtin_name(parser->vm, e->v.idx); - if (comp_is_strict(parser->vm)) { - push_error(parser, "strict: redefinition of builtin '%s'", - str(e->v.s)); - } - return btrue; - } - return bfalse; - } - if (comp_is_strict(parser->vm)) { - bfuncinfo *finfo = parser->finfo; - if ((e->type == ETVOID) && (finfo->prev || finfo->binfo->prev || parser->islocal)) { - push_error(parser, "strict: no global '%s', did you mean 'var %s'?", - str(e->v.s), str(e->v.s)); - } - } - return e->type == ETVOID; -} - -static void assign_expr(bparser *parser) -{ - bexpdesc e; - btokentype op; - int line = parser->lexer.linenumber; - parser->finfo->binfo->sideeffect = 0; /* reinit side effect marker */ - expr(parser, &e); /* left expression */ - check_symbol(parser, &e); - op = get_assign_op(parser); - if (op != OP_NOT_ASSIGN) { /* assign operator */ - bexpdesc e1; - parser->finfo->binfo->sideeffect = 1; - scan_next_token(parser); - compound_assign(parser, op, &e, &e1); - if (check_newvar(parser, &e)) { /* new variable */ - new_var(parser, e.v.s, &e); - } - if (be_code_setvar(parser->finfo, &e, &e1, bfalse)) { - parser->lexer.linenumber = line; - parser_error(parser, - "try to assign constant expressions."); - } - } else if (e.type >= ETMEMBER) { - bfuncinfo *finfo = parser->finfo; - /* these expressions occupy a register and need to be freed */ - finfo->freereg = (bbyte)be_list_count(finfo->local); - } else if (e.type == ETVOID) { /* not assign expression */ - /* undeclared symbol */ - parser->lexer.linenumber = line; - check_var(parser, &e); - } -} - -/* conditional expression */ -static void cond_expr(bparser *parser, bexpdesc *e) -{ - /* expr '?' expr ':' expr */ - if (next_type(parser) == OptQuestion) { - int jf, jl = NO_JUMP; /* jump list */ - bfuncinfo *finfo = parser->finfo; - check_var(parser, e); /* check if valid */ - scan_next_token(parser); /* skip '?' */ - be_code_jumpbool(finfo, e, bfalse); /* go if true */ - jf = e->f; - expr(parser, e); - check_var(parser, e); - be_code_nextreg(finfo, e); - be_code_freeregs(finfo, 1); - be_code_conjump(finfo, &jl, be_code_jump(finfo)); /* connect jump */ - be_code_patchjump(finfo, jf); - match_token(parser, OptColon); /* match and skip ':' */ - expr(parser, e); - check_var(parser, e); - e->v.idx = be_code_nextreg(finfo, e); - be_code_patchjump(finfo, jl); - e->type = ETREG; - } -} - -/* binary operator: + - * / % && || < <= == != > >= - * unary operator: + - ! - */ -static void sub_expr(bparser *parser, bexpdesc *e, int prio) -{ - bfuncinfo *finfo = parser->finfo; - btokentype op = get_unary_op(parser); /* check if first token in unary op */ - if (op != OP_NOT_UNARY) { /* unary op found */ - int line, res; - scan_next_token(parser); /* move to next token */ - line = parser->lexer.linenumber; /* remember line number for error reporting */ - sub_expr(parser, e, UNARY_OP_PRIO); /* parse subexpr with new prio */ - check_var(parser, e); /* check that the value is ok */ - res = be_code_unop(finfo, op, e); /* apply unary op with optimizations if the token is a value */ - if (res) { /* encode unary op */ - parser->lexer.linenumber = line; - push_error(parser, "wrong type argument to unary '%s'", - res == 1 ? "negative" : "bit-flip"); - } - } else { - suffix_expr(parser, e); /* parse left part of binop */ - } - op = get_binop(parser); /* check if binop */ - while (op != OP_NOT_BINARY && prio > binary_op_prio(op)) { /* is binop applicable */ - bexpdesc e2; - check_var(parser, e); /* check that left part is valid */ - scan_next_token(parser); /* move to next token */ - be_code_prebinop(finfo, op, e); /* and or */ - if (op == OptConnect) { - parser->finfo->binfo->sideeffect = 1; - } - init_exp(&e2, ETVOID, 0); - sub_expr(parser, &e2, binary_op_prio(op)); /* parse right side */ - if ((op == OptConnect) && (e2.type == ETVOID) && (e2.v.s == NULL)) { /* 'e2.v.s == NULL' checks that it's not an undefined variable */ - init_exp(&e2, ETINT, M_IMAX); - } else { - check_var(parser, &e2); /* check if valid */ - } - be_code_binop(finfo, op, e, &e2, -1); /* encode binary op */ - op = get_binop(parser); /* is there a following binop? */ - } - if (prio == ASSIGN_OP_PRIO) { - cond_expr(parser, e); - } -} - -static void walrus_expr(bparser *parser, bexpdesc *e) -{ - int line = parser->lexer.linenumber; - sub_expr(parser, e, ASSIGN_OP_PRIO); /* left expression */ - btokentype op = next_type(parser); - if (op == OptWalrus) { - check_symbol(parser, e); - bexpdesc e1 = *e; /* copy var to e1, e will get the result of expression */ - parser->finfo->binfo->sideeffect = 1; /* has side effect */ - scan_next_token(parser); /* skip ':=' */ - expr(parser, e); - check_var(parser, e); - if (check_newvar(parser, &e1)) { /* new variable */ - new_var(parser, e1.v.s, &e1); - } - if (be_code_setvar(parser->finfo, &e1, e, btrue /* do not release register */ )) { - parser->lexer.linenumber = line; - parser_error(parser, - "try to assign constant expressions."); - } - } -} - -/* Parse new expression and return value in `e` (overwritten) */ -/* Initializes an empty expdes and parse subexpr */ -/* Always allocates a new temp register at top of freereg */ -static void expr(bparser *parser, bexpdesc *e) -{ - init_exp(e, ETVOID, 0); - walrus_expr(parser, e); -} - -static void expr_stmt(bparser *parser) -{ - assign_expr(parser); -} - -static int block_follow(bparser *parser) -{ - switch (next_type(parser)) { - case KeyElse: case KeyElif: - case KeyEnd: case KeyExcept: - case TokenEOS: - return 0; - default: - return 1; - } -} - -static int cond_stmt(bparser *parser) -{ - bexpdesc e; - /* expr */ - match_notoken(parser, OptRBK); - expr(parser, &e); - check_var(parser, &e); - be_code_jumpbool(parser->finfo, &e, bfalse); /* go if true */ - return e.f; -} - -static void condition_block(bparser *parser, int *jmp) -{ - bfuncinfo *finfo = parser->finfo; - int br = cond_stmt(parser); - block(parser, 0); - if (next_type(parser) == KeyElif - || next_type(parser) == KeyElse) { - be_code_conjump(finfo, jmp, be_code_jump(finfo)); /* connect jump */ - } - be_code_patchjump(finfo, br); -} - -static void if_stmt(bparser *parser) -{ - int jl = NO_JUMP; /* jump list */ - /* IF expr block {ELSEIF expr block}, [ELSE block], end */ - scan_next_token(parser); /* skip 'if' */ - condition_block(parser, &jl); - while (match_skip(parser, KeyElif)) { /* 'elif' */ - condition_block(parser, &jl); - } - if (match_skip(parser, KeyElse)) { /* 'else' */ - block(parser, 0); - } - match_token(parser, KeyEnd); /* skip end */ - be_code_patchjump(parser->finfo, jl); -} - -static void do_stmt(bparser *parser) -{ - /* DO block END */ - scan_next_token(parser); /* skip 'do' */ - block(parser, 0); - match_token(parser, KeyEnd); /* skip 'end' */ -} - -static void while_stmt(bparser *parser) -{ - int brk; - bblockinfo binfo; - bfuncinfo *finfo = parser->finfo; - /* WHILE expr block END */ - scan_next_token(parser); /* skip 'while' */ - begin_block(parser->finfo, &binfo, BLOCK_LOOP); - brk = cond_stmt(parser); - stmtlist(parser); - end_block(parser); - be_code_patchjump(finfo, brk); - match_token(parser, KeyEnd); /* skip 'end' */ -} - -static bstring* for_itvar(bparser *parser) -{ - bstring *str; - if (match_id(parser, str) == NULL) { - push_error(parser, - "missing iteration variable before '%s'", - token2str(parser)); - } - return str; -} - -static void for_init(bparser *parser, bexpdesc *v) -{ - bexpdesc e; - bstring *s; - bfuncinfo *finfo = parser->finfo; - /* .it = __iterator__(expr) */ - s = parser_newstr(parser, "__iterator__"); - init_exp(&e, ETGLOBAL, be_builtin_find(parser->vm, s)); - be_code_nextreg(finfo, &e); /* code function '__iterator__' */ - expr(parser, v); - check_var(parser, v); - be_code_nextreg(finfo, v); - be_code_call(finfo, e.v.idx, 1); /* call __iterator__(expr) */ - be_code_freeregs(finfo, 1); /* free register of __iterator__ */ - s = parser_newstr(parser, ".it"); - init_exp(v, ETLOCAL, new_localvar(parser, s)); -} - -static void for_iter(bparser *parser, bstring *var, bexpdesc *it) -{ - bexpdesc e; - bfuncinfo *finfo = parser->finfo; - /* reset the jump head PC of the for loop body */ - finfo->binfo->beginpc = finfo->pc; - /* itvar = .it() */ - init_exp(&e, ETLOCAL, new_localvar(parser, var)); /* new itvar */ - be_code_setvar(finfo, &e, it, bfalse); /* code function to variable '.it' */ - be_code_call(finfo, e.v.idx, 0); /* itvar <- call .it() */ - stmtlist(parser); -} - -static void for_leave(bparser *parser, int jcatch, int beginpc) -{ - bexpdesc e; - bfuncinfo *finfo = parser->finfo; - int jbrk = finfo->binfo->breaklist; - init_exp(&e, ETSTRING, 0); - e.v.s = parser_newstr(parser, "stop_iteration"); - end_block_ex(parser, beginpc); /* leave except & loop block */ - if (jbrk != NO_JUMP) { /* has `break` statement in iteration block */ - be_code_exblk(finfo, 1); - jbrk = be_code_jump(finfo); - } - be_code_conjump(finfo, &jcatch, finfo->pc); - be_code_catch(finfo, be_code_nextreg(finfo, &e), 1, 0, NULL); - be_code_raise(finfo, NULL, NULL); - be_code_conjump(finfo, &jbrk, finfo->pc); - be_code_freeregs(finfo, 1); -} - -/* approximate equivalent script code: - * .it = __iter__(expr) - * try - * while (1) - * itvar = .it() - * stmtlist - * end - * except ('stop_iteration') - * end - * */ -static void for_stmt(bparser *parser) -{ - bstring *var; - bexpdesc iter; - bblockinfo binfo; - int jcatch, beginpc = parser->finfo->pc; - /* FOR ID : expr block END */ - scan_next_token(parser); /* skip 'for' */ - begin_block(parser->finfo, &binfo, BLOCK_EXCEPT | BLOCK_LOOP); - var = for_itvar(parser); - match_token(parser, OptColon); /* skip ':' */ - for_init(parser, &iter); - jcatch = be_code_exblk(parser->finfo, 0); - for_iter(parser, var, &iter); - for_leave(parser, jcatch, beginpc); - match_token(parser, KeyEnd); /* skip 'end' */ -} - -static bblockinfo* break_block(bparser *parser) -{ - int try_depth = 0; /* count of exception catch blocks */ - bblockinfo *binfo = parser->finfo->binfo; - /* BREAK | CONTINUE */ - scan_next_token(parser); /* skip 'break' or 'continue' */ - while (binfo && !(binfo->type & BLOCK_LOOP)) { - if (binfo->type & BLOCK_EXCEPT) { - ++try_depth; /* leave the exception catch block */ - } - binfo = binfo->prev; - } - if (binfo && try_depth) { /* exception catch blocks that needs to leave */ - be_code_exblk(parser->finfo, try_depth); - } - return binfo; -} - -static void break_stmt(bparser *parser) -{ - bfuncinfo *f = parser->finfo; - bblockinfo *binfo = break_block(parser); - if (binfo != NULL) { /* connect jump */ - be_code_conjump(f, &binfo->breaklist, be_code_jump(f)); - } else { - parser_error(parser, "break not loop"); - } -} - -static void continue_stmt(bparser *parser) -{ - bfuncinfo *f = parser->finfo; - bblockinfo *b = break_block(parser); - if (b != NULL) { /* connect jump */ - be_code_conjump(f, &b->continuelist, be_code_jump(f)); - } else { - parser_error(parser, "continue not loop"); - } -} - -static bbool isoverloadable(btokentype type) -{ - return (type >= OptAdd && type <= OptConnect) /* overloaded binary operator */ - || type == OptFlip || type == OptLBK; /* '~' and '()' operator */ -} - -static bstring* func_name(bparser* parser, bexpdesc* e, int ismethod) -{ - btokentype type = next_type(parser); - if (type == TokenId) { - bstring *name = next_token(parser).u.s; - if (!ismethod) { - new_var(parser, name, e); /* new variable */ - } - scan_next_token(parser); /* skip name */ - return name; - } else if (ismethod && isoverloadable(type)) { - scan_next_token(parser); /* skip token */ - /* '-*' negative operator */ - if (type == OptSub && next_type(parser) == OptMul) { - scan_next_token(parser); /* skip '*' */ - return parser_newstr(parser, "-*"); - } - /* '()' call operator */ - if (type == OptLBK && next_type(parser) == OptRBK) { - scan_next_token(parser); /* skip ')' */ - return parser_newstr(parser, "()"); - } - return parser_newstr(parser, be_tokentype2str(type)); - } - push_error(parser, - "the token '%s' is not a valid function name.", - token2str(parser)); - return NULL; -} - -static void def_stmt(bparser *parser) -{ - bexpdesc e; - bproto *proto; - bfuncinfo *finfo = parser->finfo; - /* 'def' ID '(' varlist ')' block 'end' */ - scan_next_token(parser); /* skip 'def' */ - proto = funcbody(parser, func_name(parser, &e, 0), NULL, 0); - be_code_closure(finfo, &e, be_code_proto(finfo, proto)); - be_stackpop(parser->vm, 1); -} - -static void return_stmt(bparser *parser) -{ - bexpdesc e; - /* 'return' expr */ - scan_next_token(parser); /* skip 'return' */ - expr(parser, &e); - if (e.v.s) { /* expression is not empty */ - check_var(parser, &e); - } - be_code_ret(parser->finfo, &e); -} - -static void check_class_attr(bparser *parser, bclass *c, bstring *attr) -{ - if (be_class_attribute(parser->vm, c, attr) != BE_NONE) { - push_error(parser, - "redefinition of the attribute '%s'", str(attr)); - } -} - -static void classvar_stmt(bparser *parser, bclass *c) -{ - bstring *name; - /* 'var' ID {',' ID} */ - scan_next_token(parser); /* skip 'var' */ - if (match_id(parser, name) != NULL) { - check_class_attr(parser, c, name); - be_class_member_bind(parser->vm, c, name, btrue); - while (match_skip(parser, OptComma)) { /* ',' */ - if (match_id(parser, name) != NULL) { - check_class_attr(parser, c, name); - be_class_member_bind(parser->vm, c, name, btrue); - } else { - parser_error(parser, "class var error"); - } - } - } else { - parser_error(parser, "class var error"); - } -} - -static void class_static_assignment_expr(bparser *parser, bexpdesc *e, bstring *name) -{ - if (match_skip(parser, OptAssign)) { /* '=' */ - bexpdesc e1, e2; - /* parse the right expression */ - expr(parser, &e2); - - e1 = *e; /* copy the class description */ - bexpdesc key; /* build the member key */ - init_exp(&key, ETSTRING, 0); - key.v.s = name; - - be_code_member(parser->finfo, &e1, &key); /* compute member accessor */ - be_code_setvar(parser->finfo, &e1, &e2, bfalse); /* set member */ - } -} - -static void classdef_stmt(bparser *parser, bclass *c, bbool is_static) -{ - bexpdesc e; - bstring *name; - bproto *proto; - /* 'def' ID '(' varlist ')' block 'end' */ - scan_next_token(parser); /* skip 'def' */ - name = func_name(parser, &e, 1); - check_class_attr(parser, c, name); - proto = funcbody(parser, name, c, is_static ? FUNC_STATIC : FUNC_METHOD); - be_class_method_bind(parser->vm, c, proto->name, proto, is_static); - be_stackpop(parser->vm, 1); -} - -static void classstaticclass_stmt(bparser *parser, bclass *c_out, bexpdesc *e_out); - -static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e) -{ - bstring *name; - /* 'static' ['var'] ID ['=' expr] {',' ID ['=' expr] } */ - /* 'static' 'def' ID '(' varlist ')' block 'end' */ - scan_next_token(parser); /* skip 'static' */ - if (next_type(parser) == KeyDef) { /* 'static' 'def' ... */ - classdef_stmt(parser, c, btrue); - } else if (next_type(parser) == KeyClass) { /* 'static' 'class' ... */ - classstaticclass_stmt(parser, c, e); - } else { - if (next_type(parser) == KeyVar) { - scan_next_token(parser); /* skip 'var' if any */ - } - if (match_id(parser, name) != NULL) { - check_class_attr(parser, c, name); - be_class_member_bind(parser->vm, c, name, bfalse); - class_static_assignment_expr(parser, e, name); - - while (match_skip(parser, OptComma)) { /* ',' */ - if (match_id(parser, name) != NULL) { - check_class_attr(parser, c, name); - be_class_member_bind(parser->vm, c, name, bfalse); - class_static_assignment_expr(parser, e, name); - } else { - parser_error(parser, "class static error"); - } - } - } else { - parser_error(parser, "class static error"); - } - } -} - -static void class_inherit(bparser *parser, bexpdesc *e) -{ - if (next_type(parser) == OptColon) { /* ':' */ - bexpdesc ec = *e; /* work on a copy because we preserve original class */ - bexpdesc e1; - scan_next_token(parser); /* skip ':' */ - expr(parser, &e1); - check_var(parser, &e1); - be_code_setsuper(parser->finfo, &ec, &e1); - } -} - -static void class_block(bparser *parser, bclass *c, bexpdesc *e) -{ - /* { [;] } */ - while (block_follow(parser)) { - switch (next_type(parser)) { - case KeyVar: classvar_stmt(parser, c); break; - case KeyStatic: classstatic_stmt(parser, c, e); break; - case KeyDef: classdef_stmt(parser, c, bfalse); break; - case OptSemic: scan_next_token(parser); break; - default: push_error(parser, - "unexpected token '%s'", token2str(parser)); - } - } -} - -static void class_stmt(bparser *parser) -{ - bstring *name; - /* 'class' ID [':' ID] class_block 'end' */ - scan_next_token(parser); /* skip 'class' */ - if (match_id(parser, name) != NULL) { - bexpdesc e; - bclass *c = be_newclass(parser->vm, name, NULL); - new_var(parser, name, &e); - be_code_class(parser->finfo, &e, c); - class_inherit(parser, &e); - - bblockinfo binfo; - begin_block(parser->finfo, &binfo, 0); - - bstring *class_str = parser_newstr(parser, "_class"); /* we always define `_class` local variable */ - bexpdesc e1; /* if inline class, we add a second local variable for _class */ - init_exp(&e1, ETLOCAL, 0); - e1.v.idx = new_localvar(parser, class_str); - be_code_setvar(parser->finfo, &e1, &e, btrue); - - begin_varinfo(parser, class_str); - - class_block(parser, c, &e); - end_block(parser); - - be_class_compress(parser->vm, c); /* compress class size */ - match_token(parser, KeyEnd); /* skip 'end' */ - } else { - parser_error(parser, "class name error"); - } -} - -static void classstaticclass_stmt(bparser *parser, bclass *c_out, bexpdesc *e_out) -{ - bstring *name; - /* [preceding 'static'] 'class' ID [':' ID] class_block 'end' */ - scan_next_token(parser); /* skip 'class' */ - if (match_id(parser, name) != NULL) { - bexpdesc e_class; /* new class object */ - check_class_attr(parser, c_out, name); /* check that the class names does not collide with another member */ - be_class_member_bind(parser->vm, c_out, name, bfalse); /* add the member slot as static */ - /* create the class object */ - bclass *c = be_newclass(parser->vm, name, NULL); - new_var(parser, name, &e_class); /* add a local var to the static initialization code for static members */ - be_code_class(parser->finfo, &e_class, c); - class_inherit(parser, &e_class); - class_block(parser, c, &e_class); - be_class_compress(parser->vm, c); /* compress class size */ - match_token(parser, KeyEnd); /* skip 'end' */ - /* add the code to copy the class object to the static member */ - bexpdesc e1 = *e_out; /* copy the class description */ - bexpdesc key; /* build the member key */ - init_exp(&key, ETSTRING, 0); - key.v.s = name; - /* assign the class to the static member */ - be_code_member(parser->finfo, &e1, &key); /* compute member accessor */ - be_code_setvar(parser->finfo, &e1, &e_class, bfalse); /* set member */ - } else { - parser_error(parser, "class name error"); - } -} - -static void import_stmt(bparser *parser) -{ - bstring *name; /* variable name */ - bexpdesc m, v; - /* 'import' (ID (['as' ID] | {',' ID}) | STRING 'as' ID ) */ - scan_next_token(parser); /* skip 'import' */ - init_exp(&m, ETSTRING, 0); - m.v.s = name = next_token(parser).u.s; - if (next_type(parser) == TokenString) { /* STRING 'as' ID */ - scan_next_token(parser); /* skip the module path */ - match_token(parser, KeyAs); /* match and skip 'as' */ - name = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - } else { /* ID (['as' ID] | {',' ID}) */ - match_token(parser, TokenId); /* match and skip ID */ - if (match_skip(parser, KeyAs)) { /* 'as' */ - name = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - } else { /* {',' ID} */ - while (match_skip(parser, OptComma)) { /* ',' */ - new_var(parser, name, &v); - be_code_import(parser->finfo, &m, &v); /* code import */ - init_exp(&m, ETSTRING, 0); /* scanning for next node */ - m.v.s = name = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - } - } - } - new_var(parser, name, &v); - be_code_import(parser->finfo, &m, &v); -} - -static void var_field(bparser *parser) -{ - /* ID ['=' expr] */ - bexpdesc e1, e2; - bstring *name; - name = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - if (match_skip(parser, OptAssign)) { /* '=' */ - expr(parser, &e2); - check_var(parser, &e2); - } else { - init_exp(&e2, ETNIL, 0); - } - new_var(parser, name, &e1); /* new variable */ - be_code_setvar(parser->finfo, &e1, &e2, bfalse); -} - -static void var_stmt(bparser *parser) -{ - /* 'var' ID ['=' expr] {',' ID ['=' expr]} */ - scan_next_token(parser); /* skip 'var' */ - var_field(parser); - while (match_skip(parser, OptComma)) { /* ',' */ - var_field(parser); - } -} - -static int except_case_list(bparser *parser, int *base) -{ - int idx; - bexpdesc e; - bfuncinfo *finfo = parser->finfo; - /* expr {',' expr} | '..' */ - if (match_skip(parser, OptConnect)) { /* '..' */ - *base = finfo->freereg; - return 0; - } - expr(parser, &e); /* first exception expression */ - check_var(parser, &e); - *base = idx = be_code_nextreg(finfo, &e); - while (match_skip(parser, OptComma)) { /* ',' */ - expr(parser, &e); - check_var(parser, &e); - idx = be_code_nextreg(finfo, &e); - } - idx = idx - *base + 1; /* count of exception expression */ - be_code_freeregs(finfo, idx); - return idx; -} - -static int except_var_list(bparser *parser, int base) -{ - bexpdesc v; - (void)base; /* unused variable (no debugging) */ - /* [as ID [, ID]] */ - if (match_skip(parser, KeyAs)) { /* 'as' */ - bstring *name = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - new_var(parser, name, &v); /* new local variable */ - be_assert(v.type == ETLOCAL && v.v.idx == base); - if (match_skip(parser, OptComma)) { /* match and skip ',' */ - name = next_token(parser).u.s; - match_token(parser, TokenId); /* match and skip ID */ - new_var(parser, name, &v); /* new local variable */ - be_assert(v.type == ETLOCAL && v.v.idx == base + 1); - return 2; - } - return 1; - } - return 0; -} - -static void except_block(bparser *parser, int *jmp, int *jbrk) -{ - int base = 0; /* the first register of the catch opcode */ - int ecnt = 0; /* exception cases count */ - int vcnt = 0; /* exception variable count */ - bblockinfo binfo; - bfuncinfo *finfo = parser->finfo; - /* 'except' (expr {',' expr} | '..') ['as' ID [',' ID]] */ - match_token(parser, KeyExcept); /* skip 'except' */ - begin_block(finfo, &binfo, 0); /* begin catch block */ - /* link from the previous except failure point */ - be_code_conjump(finfo, jmp, finfo->pc); - /* (expr {',' expr} | '..') ['as' ID [',' ID]] */ - ecnt = except_case_list(parser, &base); - vcnt = except_var_list(parser, base); - be_code_catch(finfo, base, ecnt, vcnt, jmp); - stmtlist(parser); - be_code_conjump(finfo, jbrk, be_code_jump(finfo)); - end_block(parser); /* leave catch block */ -} - -static void try_stmt(bparser *parser) -{ - int jcatch, jbrk; - /* 'try' block 'except' except_stmt block 'end' */ - scan_next_token(parser); /* skip 'try' */ - jcatch = be_code_exblk(parser->finfo, 0); - block(parser, BLOCK_EXCEPT); - be_code_exblk(parser->finfo, 1); - jbrk = be_code_jump(parser->finfo); - except_block(parser, &jcatch, &jbrk); - while (next_type(parser) == KeyExcept) { - except_block(parser, &jcatch, &jbrk); - } - be_code_patchjump(parser->finfo, jcatch); - be_code_raise(parser->finfo, NULL, NULL); - be_code_patchjump(parser->finfo, jbrk); - match_token(parser, KeyEnd); /* skip 'end' */ -} - -static void throw_stmt(bparser *parser) -{ - bexpdesc e1, e2; - /* 'raise' expr */ - scan_next_token(parser); /* skip 'raise' */ - expr(parser, &e1); - check_var(parser, &e1); - if (match_skip(parser, OptComma)) { - expr(parser, &e2); - check_var(parser, &e2); - be_code_raise(parser->finfo, &e1, &e2); - } else { - be_code_raise(parser->finfo, &e1, NULL); - } -} - -static void statement(bparser *parser) -{ - /* save value of sideeffect */ - bbyte sideeffect = parser->finfo->binfo->sideeffect; - parser->finfo->binfo->sideeffect = 1; /* by default declare side effect */ - switch (next_type(parser)) { - case KeyIf: if_stmt(parser); break; - case KeyWhile: while_stmt(parser); break; - case KeyFor: for_stmt(parser); break; - case KeyDo: do_stmt(parser); break; - case KeyBreak: break_stmt(parser); break; - case KeyContinue: continue_stmt(parser); break; - case KeyDef: def_stmt(parser); break; - case KeyClass: class_stmt(parser); break; - case KeyReturn: return_stmt(parser); break; - case KeyImport: import_stmt(parser); break; - case KeyVar: var_stmt(parser); break; - case KeyTry: try_stmt(parser); break; - case KeyRaise: throw_stmt(parser); break; - case OptSemic: - parser->finfo->binfo->sideeffect = sideeffect; /* restore sideeffect */ - scan_next_token(parser); break; /* empty statement */ - default: - parser->finfo->binfo->sideeffect = sideeffect; /* restore sideeffect */ - expr_stmt(parser); - if (comp_is_strict(parser->vm) && parser->finfo->binfo->sideeffect == 0) { - push_error(parser, "strict: expression without side effect detected"); - } - break; - } - be_assert(parser->finfo->freereg >= be_list_count(parser->finfo->local)); -} - -static void stmtlist(bparser *parser) -{ - while (block_follow(parser)) { - statement(parser); - } -} - -static void block(bparser *parser, int type) -{ - bblockinfo binfo; - begin_block(parser->finfo, &binfo, type); - stmtlist(parser); - end_block(parser); -} - -static void mainfunc(bparser *parser, bclosure *cl) -{ - bblockinfo binfo; - bfuncinfo finfo; - begin_func(parser, &finfo, &binfo); - finfo.proto->argc = 0; /* args */ - finfo.proto->name = be_newstr(parser->vm, funcname(parser)); - cl->proto = finfo.proto; - be_remove(parser->vm, -3); /* pop proto from stack */ - stmtlist(parser); - end_func(parser); - match_token(parser, TokenEOS); /* skip EOS */ -} - -bclosure* be_parser_source(bvm *vm, - const char *fname, breader reader, void *data, bbool islocal) -{ - bparser parser; - bclosure *cl = be_newclosure(vm, 0); - parser.vm = vm; - parser.finfo = NULL; - parser.cl = cl; - parser.islocal = (bbyte)islocal; - var_setclosure(vm->top, cl); - be_stackpush(vm); - be_lexer_init(&parser.lexer, vm, fname, reader, data); - scan_next_token(&parser); /* scan first token */ - mainfunc(&parser, cl); - be_lexer_deinit(&parser.lexer); - be_global_release_space(vm); /* clear global space */ - be_stackpop(vm, 2); /* pop strtab */ - scan_next_token(&parser); /* clear lexer */ - return cl; -} - -#endif diff --git a/lib/libesp32/Berry/src/be_parser.h b/lib/libesp32/Berry/src/be_parser.h deleted file mode 100644 index 9b7d11e0e2fb..000000000000 --- a/lib/libesp32/Berry/src/be_parser.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_PARSER_H -#define BE_PARSER_H - -#include "be_object.h" -#include "be_string.h" - -typedef enum { - ETVOID, /* unknown (new variable or error) */ - ETNIL, - ETBOOL, - ETREAL, - ETINT, - ETSTRING, - ETPROTO, - ETCONST, - ETLOCAL, /* local variable, allocated until end of scope */ - ETGLOBAL, /* global by index number */ - ETUPVAL, - ETMEMBER, /* member accessor (by name) */ - ETINDEX, /* index accessor (ex array index) */ - ETREG, /* temporary register, can be freed if top of stack */ - ETNGLOBAL /* named global */ -} exptype_t; - -typedef struct { - union { - struct { /* for suffix */ - unsigned int idx:9; /* suffix RK index */ - unsigned int obj:9; /* object RK index */ - unsigned int tt:5; /* object type */ - } ss; - breal r; /* for ETREAL */ - bint i; /* for ETINT */ - bstring *s; /* for ETSTRING */ - bproto *p; /* for ETPROTO */ - int idx; /* variable index */ - } v; - int t; /* patch list of 'exit when true' */ - int f; /* patch list of 'exit when false' */ - bbyte not; /* not mark */ - bbyte type; -} bexpdesc; - -typedef struct bblockinfo { - struct bblockinfo *prev; - bbyte nactlocals; /* number of active local variables */ - bbyte type; /* block type mask */ - bbyte hasupval; /* has upvalue mark */ - bbyte sideeffect; /* did the last expr/statement had a side effect */ - int lastjmp; /* pc for the last jump, prevents false register optimizations */ - int breaklist; /* break list */ - int beginpc; /* begin pc */ - int continuelist; /* continue list */ -} bblockinfo; - -typedef struct bfuncinfo { - struct bfuncinfo *prev; /* outer function */ - bproto *proto; /* the function prototype */ - bblockinfo *binfo; /* block information */ - struct blexer *lexer; /* the lexer pointer */ - blist *local; /* local variable */ - bmap *upval; /* upvalue variable */ - bvector code; /* code vector */ - bvector kvec; /* constants table */ - bvector pvec; /* proto table */ -#if BE_DEBUG_RUNTIME_INFO /* debug information */ - bvector linevec; -#endif -#if BE_DEBUG_VAR_INFO - bvector varvec; -#endif - int pc; /* program count */ - bbyte freereg; /* first free register */ - bbyte flags; /* some flages */ -} bfuncinfo; - -/* code block type definitions */ -#define BLOCK_LOOP 1 -#define BLOCK_EXCEPT 2 - -bclosure *be_parser_source(bvm *vm, - const char *fname, breader reader, void *data, bbool islocal); - -#endif diff --git a/lib/libesp32/Berry/src/be_rangelib.c b/lib/libesp32/Berry/src/be_rangelib.c deleted file mode 100644 index 187807021205..000000000000 --- a/lib/libesp32/Berry/src/be_rangelib.c +++ /dev/null @@ -1,187 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_func.h" -#include "be_vm.h" - -static int m_init(bvm *vm) -{ - int argc = be_top(vm); - if (argc < 3) { be_raise(vm, "value_error", "missing arguments"); } - if (!be_isint(vm, 2) || !be_isint(vm, 3)) { be_raise(vm, "value_error", "arguments must be 'int'"); } - be_pushvalue(vm, 2); - be_setmember(vm, 1, "__lower__"); - be_pop(vm, 1); - be_pushvalue(vm, 3); - be_setmember(vm, 1, "__upper__"); - int incr = 1; /* default increment is '1' */ - if (argc >= 4) { - if (!be_isint(vm, 4)) { be_raise(vm, "value_error", "arguments must be 'int'"); } - incr = be_toint(vm, 4); - if (incr == 0) { be_raise(vm, "value_error", "increment cannot be zero"); } - } - be_pushint(vm, incr); - be_setmember(vm, 1, "__incr__"); - be_return_nil(vm); -} - -static int m_tostring(bvm *vm) -{ - be_getmember(vm, 1, "__incr__"); - int incr = be_toint(vm, -1); - be_pop(vm, 1); - if (incr == 1) { - be_pushstring(vm, "("); - be_getmember(vm, 1, "__lower__"); - be_tostring(vm, -1); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_pushstring(vm, ".."); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_getmember(vm, 1, "__upper__"); - be_tostring(vm, -1); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_pushstring(vm, ")"); - be_strconcat(vm, -2); - be_pop(vm, 1); - } else { - be_pushstring(vm, "range("); - be_getmember(vm, 1, "__lower__"); - be_tostring(vm, -1); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_pushstring(vm, ", "); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_getmember(vm, 1, "__upper__"); - be_tostring(vm, -1); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_pushstring(vm, ", "); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_getmember(vm, 1, "__incr__"); - be_tostring(vm, -1); - be_strconcat(vm, -2); - be_pop(vm, 1); - be_pushstring(vm, ")"); - be_strconcat(vm, -2); - be_pop(vm, 1); - } - be_return(vm); -} - -static int m_upper(bvm *vm) -{ - be_getmember(vm, 1, "__upper__"); - be_return(vm); -} - -static int m_lower(bvm *vm) -{ - be_getmember(vm, 1, "__lower__"); - be_return(vm); -} - -static int m_incr(bvm *vm) -{ - be_getmember(vm, 1, "__incr__"); - be_return(vm); -} - -static int m_setrange(bvm *vm) -{ - int argc = be_top(vm); - if (argc < 3) { be_raise(vm, "value_error", "missing arguments"); } - if (!be_isint(vm, 2) || !be_isint(vm, 3)) { be_raise(vm, "value_error", "arguments must be 'int'"); } - be_pushvalue(vm, 2); - be_setmember(vm, 1, "__lower__"); - be_pop(vm, 1); - be_pushvalue(vm, 3); - be_setmember(vm, 1, "__upper__"); - int incr = 1; /* default increment is '1' */ - if (argc >= 4) { - if (!be_isint(vm, 4)) { be_raise(vm, "value_error", "arguments must be 'int'"); } - incr = be_toint(vm, 4); - if (incr == 0) { be_raise(vm, "value_error", "increment cannot be zero"); } - } - be_pushint(vm, incr); - be_setmember(vm, 1, "__incr__"); - be_return_nil(vm); -} - -static int iter_closure(bvm *vm) -{ - /* for better performance, we operate the upvalues - * directly without using by the stack. */ - bntvclos *func = var_toobj(vm->cf->func); - bvalue *uv0 = be_ntvclos_upval(func, 0)->value; - bvalue *uv1 = be_ntvclos_upval(func, 1)->value; - bvalue *uv2 = be_ntvclos_upval(func, 2)->value; - bint lower = var_toint(uv0); /* upvalue[0] => lower */ - bint upper = var_toint(uv1); /* upvalue[1] => upper */ - bint incr = var_toint(uv2); /* upvalue[2] => incr */ - if ((incr > 0 && lower > upper) || (incr < 0 && lower < upper)) { - be_stop_iteration(vm); - } - var_toint(uv0) = lower + incr; /* set upvale[0] */ - be_pushint(vm, lower); /* push the return value */ - be_return(vm); -} - -static int m_iter(bvm *vm) -{ - be_pushntvclosure(vm, iter_closure, 3); - be_getmember(vm, 1, "__lower__"); - be_setupval(vm, -2, 0); - be_pop(vm, 1); - be_getmember(vm, 1, "__upper__"); - be_setupval(vm, -2, 1); - be_pop(vm, 1); - be_getmember(vm, 1, "__incr__"); - be_setupval(vm, -2, 2); - be_pop(vm, 1); - be_return(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -void be_load_rangelib(bvm *vm) -{ - static const bnfuncinfo members[] = { - { "__lower__", NULL }, - { "__upper__", NULL }, - { "__incr__", NULL }, - { "init", m_init }, - { "tostring", m_tostring }, - { "lower", m_lower }, - { "upper", m_upper }, - { "setrange", m_setrange }, - { "iter", m_iter }, - { NULL, NULL } - }; - be_regclass(vm, "range", members); -} -#else -/* @const_object_info_begin -class be_class_range (scope: global, name: range) { - __lower__, var - __upper__, var - __incr__, var - init, func(m_init) - tostring, func(m_tostring) - lower, func(m_lower) - upper, func(m_upper) - incr, func(m_incr) - setrange, func(m_setrange) - iter, func(m_iter) -} -@const_object_info_end */ -#include "../generate/be_fixed_be_class_range.h" -#endif diff --git a/lib/libesp32/Berry/src/be_repl.c b/lib/libesp32/Berry/src/be_repl.c deleted file mode 100644 index 17b766df797b..000000000000 --- a/lib/libesp32/Berry/src/be_repl.c +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "berry.h" -#include "be_repl.h" -#include - -#define safecall(func, ...) if (func) { func(__VA_ARGS__); } - -#if BE_USE_SCRIPT_COMPILER - -static int try_return(bvm *vm, const char *line) -{ - int res, idx; - line = be_pushfstring(vm, "return (%s)", line); - idx = be_absindex(vm, -1); /* get the source text absolute index */ - res = be_loadbuffer(vm, "stdin", line, strlen(line)); /* compile line */ - be_remove(vm, idx); /* remove source string */ - return res; -} - -static bbool is_multline(bvm *vm) -{ - const char *msg = be_tostring(vm, -1); - size_t len = strlen(msg); - if (len > 5) { /* multi-line text if the error message is 'EOS' at the end */ - return !strcmp(msg + len - 5, "'EOS'"); - } - return bfalse; -} - -static int compile(bvm *vm, char *line, breadline getl, bfreeline freel) -{ - int res = try_return(vm, line); - if (be_getexcept(vm, res) == BE_SYNTAX_ERROR) { - be_pop(vm, 2); /* pop exception values */ - be_pushstring(vm, line); - safecall(freel, line); /* free line buffer */ - for (;;) { - const char *src = be_tostring(vm, -1); /* get source code */ - int idx = be_absindex(vm, -1); /* get the source text absolute index */ - /* compile source line */ - res = be_loadbuffer(vm, "stdin", src, strlen(src)); - if (!res || !is_multline(vm)) { - be_remove(vm, idx); /* remove source code */ - return res; - } - be_pop(vm, 2); /* pop exception values */ - line = getl(">> "); /* read a new input line */ - be_pushfstring(vm, "\n%s", line); - safecall(freel, line); /* free line buffer */ - be_strconcat(vm, -2); - be_pop(vm, 1); /* pop new line */ - } - } else { - safecall(freel, line); /* free line buffer */ - } - return res; -} - -static int call_script(bvm *vm) -{ - int res = be_pcall(vm, 0); /* call the main function */ - switch (res) { - case BE_OK: /* execution succeed */ - if (!be_isnil(vm, -1)) { /* print return value when it's not nil */ - be_dumpvalue(vm, -1); - } - be_pop(vm, 1); /* pop the result value */ - break; - case BE_EXCEPTION: /* vm run error */ - be_dumpexcept(vm); - be_pop(vm, 1); /* pop the function value */ - break; - default: /* BE_EXIT or BE_MALLOC_FAIL */ - return res; - } - return 0; -} - -BERRY_API int be_repl(bvm *vm, breadline getline, bfreeline freeline) -{ - char *line; - be_assert(getline != NULL); - while ((line = getline("> ")) != NULL) { - int res = compile(vm, line, getline, freeline); - if (res == BE_MALLOC_FAIL) - return BE_MALLOC_FAIL; - if (res) { - be_dumpexcept(vm); - } else { /* compiled successfully */ - res = call_script(vm); - if (res) { - return res == BE_EXIT ? be_toindex(vm, -1) : res; - } - } - } - be_writenewline(); - return 0; -} - -#endif diff --git a/lib/libesp32/Berry/src/be_repl.h b/lib/libesp32/Berry/src/be_repl.h deleted file mode 100644 index 7d27e7850d62..000000000000 --- a/lib/libesp32/Berry/src/be_repl.h +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_REPL_H -#define BE_REPL_H - -#include "berry.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef char* (*breadline)(const char *prompt); -typedef void (*bfreeline)(char *ptr); - -BERRY_API int be_repl(bvm *vm, breadline getline, bfreeline freeline); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32/Berry/src/be_solidifylib.c b/lib/libesp32/Berry/src/be_solidifylib.c deleted file mode 100644 index ecfb7589065e..000000000000 --- a/lib/libesp32/Berry/src/be_solidifylib.c +++ /dev/null @@ -1,886 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_module.h" -#include "be_string.h" -#include "be_vector.h" -#include "be_class.h" -#include "be_list.h" -#include "be_debug.h" -#include "be_map.h" -#include "be_vm.h" -#include "be_decoder.h" -#include "be_sys.h" -#include "be_mem.h" -#include "be_byteslib.h" -#include "be_gc.h" -#include -#include -#include -#include - -extern const bclass be_class_list; -extern const bclass be_class_map; -extern const bclass be_class_bytes; - -#if BE_USE_SOLIDIFY_MODULE -#include - -#define be_builtin_count(vm) \ - be_vector_count(&(vm)->gbldesc.builtin.vlist) - -#ifndef INST_BUF_SIZE -#define INST_BUF_SIZE 768 -#endif - -#define logfmt(...) \ - do { \ - char __lbuf[INST_BUF_SIZE]; \ - snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__); \ - if (fout) { \ - be_fwrite(fout, __lbuf, strlen(__lbuf)); \ - } else { \ - be_writestring(__lbuf); \ - } \ - } while (0) - -/* minimal version without formatting and without size limit */ -#define lognofmt(__s) \ - do { \ - if (fout) { \ - be_fwrite(fout, __s, strlen(__s)); \ - } else { \ - be_writestring(__s); \ - } \ - } while (0) - -/********************************************************************\ - * Encode string to identifiers - * - * `_X` is used as an escape marker -\********************************************************************/ -static unsigned toidentifier_length(const char *s) -{ - unsigned len = 1; - const char * p = s; - while (*p) { - if (p[0] == '_' && p[1] == 'X') { - len += 3; - p += 2; - } else if (isalnum(p[0]) || p[0] == '_') { - p++; - len++; - } else { // escape - p++; - len += 4; - } - } - return len; -} - -inline static char hexdigit(int v) -{ - v = v & 0xF; - if (v >= 10) return v - 10 + 'A'; - return v + '0'; -} - -static void toidentifier(char *to, const char *p) -{ - while (*p) { - if (p[0] == '_' && p[1] == 'X') { - to[0] = '_'; - to[1] = 'X'; - to[2] = '_'; - p += 2; - to += 3; - } else if (isalnum(p[0]) || p[0] == '_') { - *to = *p; - to++; - p++; - } else { // escape - to[0] = '_'; - to[1] = 'X'; - to[2] = hexdigit((*p & 0xF0) >> 4); - to[3] = hexdigit(*p & 0x0F); - p++; - to += 4; - } - } - *to = 0; // final NULL -} - -static void m_solidify_bvalue(bvm *vm, bbool str_literal, const bvalue * value, const char *prefix_name, const char *key, void* fout); - -static void m_solidify_map(bvm *vm, bbool str_literal, bmap * map, const char *prefix_name, void* fout) -{ - // compact first - be_map_compact(vm, map); - - logfmt(" be_nested_map(%i,\n", map->count); - - logfmt(" ( (struct bmapnode*) &(const bmapnode[]) {\n"); - for (int i = 0; i < map->size; i++) { - bmapnode * node = &map->slots[i]; - if (node->key.type == BE_NIL) { - continue; /* key not used */ - } - int key_next = node->key.next; - if (0xFFFFFF == key_next) { - key_next = -1; /* more readable */ - } - if (node->key.type == BE_STRING) { - /* convert the string literal to identifier */ - const char * key = str(node->key.v.s); - size_t id_len = toidentifier_length(key); - char id_buf[id_len]; - toidentifier(id_buf, key); - if (!str_literal) { - logfmt(" { be_const_key(%s, %i), ", id_buf, key_next); - } else { - logfmt(" { be_const_key_weak(%s, %i), ", id_buf, key_next); - } - m_solidify_bvalue(vm, str_literal, &node->value, prefix_name, str(node->key.v.s), fout); - } else if (node->key.type == BE_INT) { -#if BE_INTGER_TYPE == 2 - logfmt(" { be_const_key_int(%lli, %i), ", node->key.v.i, key_next); -#else - logfmt(" { be_const_key_int(%i, %i), ", node->key.v.i, key_next); -#endif - m_solidify_bvalue(vm, str_literal, &node->value, prefix_name, NULL, fout); - } else { - char error[64]; - snprintf(error, sizeof(error), "Unsupported type in key: %i", node->key.type); - be_raise(vm, "internal_error", error); - } - - logfmt(" },\n"); - } - logfmt(" }))"); // TODO need terminal comma? - -} - -static void m_solidify_list(bvm *vm, bbool str_literal, const blist * list, const char *prefix_name, void* fout) -{ - logfmt(" be_nested_list(%i,\n", list->count); - - logfmt(" ( (struct bvalue*) &(const bvalue[]) {\n"); - for (int i = 0; i < list->count; i++) { - logfmt(" "); - m_solidify_bvalue(vm, str_literal, &list->data[i], prefix_name, "", fout); - logfmt(",\n"); - } - logfmt(" }))"); // TODO need terminal comma? -} - -// pass key name in case of class, or NULL if none -static void m_solidify_bvalue(bvm *vm, bbool str_literal, const bvalue * value, const char *prefix_name, const char *key, void* fout) -{ - int type = var_primetype(value); - switch (type) { - case BE_NIL: - logfmt("be_const_nil()"); - break; - case BE_BOOL: - logfmt("be_const_bool(%i)", var_tobool(value)); - break; - case BE_INT: -#if BE_INTGER_TYPE == 2 - logfmt("be_const_int(%lli)", var_toint(value)); -#else - logfmt("be_const_int(%i)", var_toint(value)); -#endif - break; - case BE_INDEX: -#if BE_INTGER_TYPE == 2 - logfmt("be_const_var(%lli)", var_toint(value)); -#else - logfmt("be_const_var(%i)", var_toint(value)); -#endif - break; - case BE_REAL: -#if BE_USE_SINGLE_FLOAT - logfmt("be_const_real_hex(0x%08" PRIX32 ")", (uint32_t)(uintptr_t)var_toobj(value)); -#else - logfmt("be_const_real_hex(0x%016" PRIx64 ")", (uint64_t)var_toobj(value)); -#endif - break; - case BE_STRING: - { - const char * str = str(var_tostr(value)); - size_t len = strlen(str); - size_t id_len = toidentifier_length(str); - char id_buf_stack[64]; - char *id_buf = id_buf_stack; - if (id_len >= 64) { - id_buf = be_os_malloc(id_len); - if (!id_buf) { - be_raise(vm, "memory_error", "could not allocated buffer"); - } - } - toidentifier(id_buf, str); - if (len >= 255) { - /* decompose to avoid any size limit */ - lognofmt("be_nested_str_long("); - lognofmt(id_buf); - lognofmt(")"); - } else if (!str_literal) { - logfmt("be_nested_str(%s)", id_buf); - } else { - logfmt("be_nested_str_weak(%s)", id_buf); - } - if (id_buf != id_buf_stack) { - be_os_free(id_buf); - } - } - break; - case BE_CLOSURE: - { - bclosure *clo = (bclosure*) var_toobj(value); - const char * func_name = str(clo->proto->name); - size_t id_len = toidentifier_length(func_name); - char func_name_id[id_len]; - toidentifier(func_name_id, func_name); - logfmt("be_const_%sclosure(%s%s%s_closure)", - var_isstatic(value) ? "static_" : "", - prefix_name ? prefix_name : "", prefix_name ? "_" : "", - func_name_id); - } - break; - case BE_CLASS: - logfmt("be_const_class(be_class_%s)", str(((bclass*) var_toobj(value))->name)); - break; - case BE_COMPTR: - logfmt("be_const_comptr(&be_ntv_%s_%s)", prefix_name ? prefix_name : "unknown", key ? key : "unknown"); - break; - case BE_NTVFUNC: - logfmt("be_const_%sfunc(be_ntv_%s_%s)", - var_isstatic(value) ? "static_" : "", - prefix_name ? prefix_name : "unknown", key ? key : "unknown"); - break; - case BE_INSTANCE: - { - binstance * ins = (binstance *) var_toobj(value); - bclass * cl = ins->_class; - - if (cl == &be_class_bytes) { - const void * bufptr = var_toobj(&ins->members[0]); - int32_t len = var_toint(&ins->members[1]); - size_t hex_len = len * 2 + 1; - - char * hex_out = be_pushbuffer(vm, hex_len); - be_bytes_tohex(hex_out, hex_len, bufptr, len); - logfmt("be_const_bytes_instance(%s)", hex_out); - be_pop(vm, 1); - } else if (ins->super || ins->sub) { - be_raise(vm, "internal_error", "instance must not have a super/sub class"); - } else { - const char * cl_ptr = ""; - if (cl == &be_class_map) { cl_ptr = "map"; } - else if (cl == &be_class_list) { cl_ptr = "list"; } - else { be_raise(vm, "internal_error", "unsupported class"); } - - logfmt("be_const_simple_instance(be_nested_simple_instance(&be_class_%s, {\n", cl_ptr); - if (cl == &be_class_map) { - logfmt(" be_const_map( * "); - } else { - logfmt(" be_const_list( * "); - } - m_solidify_bvalue(vm, str_literal, &ins->members[0], prefix_name, key, fout); - logfmt(" ) } ))"); - } - } - break; - case BE_MAP: - m_solidify_map(vm, str_literal, (bmap *) var_toobj(value), prefix_name, fout); - break; - case BE_LIST: - m_solidify_list(vm, str_literal, (blist *) var_toobj(value), prefix_name, fout); - break; - default: - { - char error[64]; - snprintf(error, sizeof(error), "Unsupported type in function constants: %i", type); - be_raise(vm, "internal_error", error); - } - } -} - -static void m_solidify_subclass(bvm *vm, bbool str_literal, const bclass *cl, void* fout); - -/* solidify any inner class */ -static void m_solidify_closure_inner_class(bvm *vm, bbool str_literal, const bclosure *clo, void* fout) -{ - // parse any class in constants to output it first - bproto *pr = clo->proto; - if ((!gc_isconst(clo)) && (pr->nconst > 0) && (!(pr->varg & BE_VA_SHARED_KTAB)) && (!(pr->varg & BE_VA_NOCOMPACT))) { /* if shared ktab or nocompact, skip */ - for (int k = 0; k < pr->nconst; k++) { - if (var_type(&pr->ktab[k]) == BE_CLASS) { - if ((k == 0) && (pr->varg & BE_VA_STATICMETHOD)) { - // it is the implicit '_class' variable from a static method, don't dump the class - } else { - // output the class - m_solidify_subclass(vm, str_literal, (bclass*) var_toobj(&pr->ktab[k]), fout); - } - } - } - } -} - -static void m_solidify_proto(bvm *vm, bbool str_literal, const bproto *pr, const char * func_name, int indent, const char * prefix_name, void* fout) -{ - logfmt("%*sbe_nested_proto(\n", indent, ""); - indent += 2; - - logfmt("%*s%d, /* nstack */\n", indent, "", pr->nstack); - logfmt("%*s%d, /* argc */\n", indent, "", pr->argc); - logfmt("%*s%d, /* varg */\n", indent, "", pr->varg); - logfmt("%*s%d, /* has upvals */\n", indent, "", (pr->nupvals > 0) ? 1 : 0); - - if (pr->nupvals > 0) { - logfmt("%*s( &(const bupvaldesc[%2d]) { /* upvals */\n", indent, "", pr->nupvals); - for (int32_t i = 0; i < pr->nupvals; i++) { - logfmt("%*s be_local_const_upval(%i, %i),\n", indent, "", pr->upvals[i].instack, pr->upvals[i].idx); - } - logfmt("%*s}),\n", indent, ""); - } else { - logfmt("%*sNULL, /* no upvals */\n", indent, ""); - } - - logfmt("%*s%d, /* has sup protos */\n", indent, "", (pr->nproto > 0) ? 1 : 0); - if (pr->nproto > 0) { - logfmt("%*s( &(const struct bproto*[%2d]) {\n", indent, "", pr->nproto); - for (int32_t i = 0; i < pr->nproto; i++) { - size_t sub_len = strlen(func_name) + 10; - char sub_name[sub_len]; - snprintf(sub_name, sizeof(sub_name), "%s_%"PRId32, func_name, i); - m_solidify_proto(vm, str_literal, pr->ptab[i], sub_name, indent+2, prefix_name, fout); - logfmt(",\n"); - } - logfmt("%*s}),\n", indent, ""); - } else { - logfmt("%*sNULL, /* no sub protos */\n", indent, ""); - } - - logfmt("%*s%d, /* has constants */\n", indent, "", (pr->nconst > 0) ? 1 : 0); - if (pr->nconst > 0) { - // we output the full table unless it's a shared ktab - if (pr->varg & BE_VA_SHARED_KTAB) { - logfmt("%*s&be_ktab_%s, /* shared constants */\n", indent, "", prefix_name); - } else { - logfmt("%*s( &(const bvalue[%2d]) { /* constants */\n", indent, "", pr->nconst); - for (int k = 0; k < pr->nconst; k++) { - logfmt("%*s/* K%-3d */ ", indent, "", k); - m_solidify_bvalue(vm, str_literal, &pr->ktab[k], NULL, NULL, fout); - logfmt(",\n"); - } - logfmt("%*s}),\n", indent, ""); - } - } else { - logfmt("%*sNULL, /* no const */\n", indent, ""); - } - - /* convert the string literal to identifier */ - const char * key = str(pr->name); - size_t id_len = toidentifier_length(key); - char id_buf[id_len]; - toidentifier(id_buf, key); - if (!str_literal) { - logfmt("%*s&be_const_str_%s,\n", indent, "", id_buf); - } else { - logfmt("%*sbe_str_weak(%s),\n", indent, "", id_buf); - } - // hard-code source as "solidified" for solidified - logfmt("%*s&be_const_str_solidified,\n", indent, ""); - - logfmt("%*s( &(const binstruction[%2d]) { /* code */\n", indent, "", pr->codesize); - for (int pc = 0; pc < pr->codesize; pc++) { - uint32_t ins = pr->code[pc]; - logfmt("%*s 0x%08"PRIX32", //", indent, "", ins); - be_print_inst(ins, pc, fout); - bopcode op = IGET_OP(ins); - if (op == OP_GETGBL || op == OP_SETGBL) { - // check if the global is in built-ins - int glb = IGET_Bx(ins); - if (glb > be_builtin_count(vm)) { - // not supported - logfmt("\n===== unsupported global G%d\n", glb); - be_raise(vm, "internal_error", "Unsupported access to non-builtin global"); - } - } - } - logfmt("%*s})\n", indent, ""); - indent -= 2; - logfmt("%*s)", indent, ""); - -} - -static void m_solidify_closure(bvm *vm, bbool str_literal, const bclosure *clo, const char * prefix_name, void* fout) -{ - bproto *pr = clo->proto; - const char * func_name = str(pr->name); - - if (clo->nupvals > 0) { - logfmt("--> Unsupported upvals in closure <---"); - // be_raise(vm, "internal_error", "Unsupported upvals in closure"); - } - - int indent = 2; - - m_solidify_closure_inner_class(vm, str_literal, clo, fout); - - logfmt("\n"); - logfmt("/********************************************************************\n"); - logfmt("** Solidified function: %s\n", func_name); - logfmt("********************************************************************/\n"); - - { - size_t id_len = toidentifier_length(func_name); - char func_name_id[id_len]; - toidentifier(func_name_id, func_name); - logfmt("be_local_closure(%s%s%s, /* name */\n", - prefix_name ? prefix_name : "", prefix_name ? "_" : "", - func_name_id); - } - - m_solidify_proto(vm, str_literal, pr, func_name, indent, prefix_name, fout); - logfmt("\n"); - - // closure - logfmt(");\n"); - logfmt("/*******************************************************************/\n\n"); -} - -static void m_compact_class(bvm *vm, bbool str_literal, const bclass *cla, void* fout); - -static void m_solidify_subclass(bvm *vm, bbool str_literal, const bclass *cla, void* fout) -{ - const char * classname = str(cla->name); - - /* TODO try compacting for now */ - m_compact_class(vm, str_literal, cla, fout); - - char prefix_name[strlen(classname) + 10]; - snprintf(prefix_name, sizeof(prefix_name), "class_%s", classname); - /* pre-declare class to support '_class' implicit variable */ - logfmt("\nextern const bclass be_class_%s;\n", classname); - - /* iterate on members to dump closures */ - if (cla->members) { - bmapnode *node; - bmapiter iter = be_map_iter(); - while ((node = be_map_next(cla->members, &iter)) != NULL) { - if (var_isstr(&node->key) && var_isclosure(&node->value)) { - bclosure *f = var_toobj(&node->value); - m_solidify_closure(vm, str_literal, f, prefix_name, fout); - } - } - } - - - logfmt("\n"); - logfmt("/********************************************************************\n"); - logfmt("** Solidified class: %s\n", classname); - logfmt("********************************************************************/\n"); - - if (cla->super) { - logfmt("extern const bclass be_class_%s;\n", str(cla->super->name)); - } - - logfmt("be_local_class(%s,\n", classname); - logfmt(" %i,\n", cla->nvar); - if (cla->super) { - logfmt(" &be_class_%s,\n", str(cla->super->name)); - } else { - logfmt(" NULL,\n"); - } - - if (cla->members) { - m_solidify_map(vm, str_literal, cla->members, prefix_name, fout); - logfmt(",\n"); - } else { - logfmt(" NULL,\n"); - } - - size_t id_len = toidentifier_length(classname); - char id_buf[id_len]; - toidentifier(id_buf, classname); - if (!str_literal) { - logfmt(" (bstring*) &be_const_str_%s\n", id_buf); - } else { - logfmt(" be_str_weak(%s)\n", id_buf); - } - logfmt(");\n"); -} - -static void m_solidify_class(bvm *vm, bbool str_literal, bclass *cl, void* fout) -{ - m_solidify_subclass(vm, str_literal, cl, fout); -} - -static void m_solidify_module(bvm *vm, bbool str_literal, bmodule *ml, void* fout) -{ - const char * modulename = be_module_name(ml); - if (!modulename) { modulename = ""; } - // char prefix_name[strlen(modulename) + 10]; - // snprintf(prefix_name, sizeof(prefix_name), "module_%s", modulename); - - /* iterate on members to dump closures and classes */ - if (ml->table) { - bmapnode *node; - bmapiter iter = be_map_iter(); - while ((node = be_map_next(ml->table, &iter)) != NULL) { - if (var_isstr(&node->key) && var_isclosure(&node->value)) { - bclosure *f = var_toobj(&node->value); - m_solidify_closure(vm, str_literal, f, NULL, fout); - } - if (var_isstr(&node->key) && var_isclass(&node->value)) { - bclass *cl = var_toobj(&node->value); - m_solidify_subclass(vm, str_literal, cl, fout); - } - } - } - - - logfmt("\n"); - logfmt("/********************************************************************\n"); - logfmt("** Solidified module: %s\n", modulename); - logfmt("********************************************************************/\n"); - - logfmt("be_local_module(%s,\n", modulename); - logfmt(" \"%s\",\n", modulename); - - if (ml->table) { - m_solidify_map(vm, str_literal, ml->table, NULL, fout); - logfmt("\n"); - } else { - logfmt(" NULL,\n"); - } - logfmt(");\n"); - logfmt("BE_EXPORT_VARIABLE be_define_const_native_module(%s);\n", modulename); - logfmt("/********************************************************************/\n"); - -} - -static int m_dump(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - bbool str_literal = bfalse; - if (top >= 2) { - str_literal = be_tobool(vm, 2); - } - void* fout = NULL; /* output file */ - if (top >= 3 && be_isinstance(vm, 3)) { - be_getmember(vm, 3, ".p"); - if (be_iscomptr(vm, -1)) { - fout = be_tocomptr(vm, -1); - } - be_pop(vm, 1); - } - const char *prefix_name = NULL; /* allow to specify an explicit prefix */ - if (top >= 4 && be_isstring(vm, 4)) { - prefix_name = be_tostring(vm, 4); - } - if (var_isclosure(v)) { - m_solidify_closure(vm, str_literal, var_toobj(v), prefix_name, fout); - } else if (var_isclass(v)) { - m_solidify_class(vm, str_literal, var_toobj(v), fout); - } else if (var_ismodule(v)) { - m_solidify_module(vm, str_literal, var_toobj(v), fout); - } else { - be_raise(vm, "value_error", "unsupported type"); - } - } - be_return_nil(vm); -} - -static void m_compact_class(bvm *vm, bbool str_literal, const bclass *cla, void* fout) -{ - const char * classname = str(cla->name); - - /* reserve an array big enough for max size ktab (256) */ - const int MAX_KTAB_SIZE = 256; - bvalue ktab[MAX_KTAB_SIZE]; /* size is 2048 byte for 32 bits, so fitting in ESP32, may need to be changed on smaller architectures */ - int ktab_size = 0; - - /* for statistics, keep the aggregate number of bvalues */ - int ktab_total = 0; - - /* iterate on members to dump closures */ - if (cla->members) { - bmapnode *node; - bmapiter iter = be_map_iter(); - - /* first iteration to build the global ktab */ - while ((node = be_map_next(cla->members, &iter)) != NULL) { - if (var_isstr(&node->key) && var_isclosure(&node->value)) { - bclosure *cl = var_toobj(&node->value); - bproto *pr = cl->proto; - - if ((gc_isconst(cl)) || (pr->varg & BE_VA_SHARED_KTAB) || (pr->varg & BE_VA_NOCOMPACT)) { continue; } - - // iterate on each bvalue in ktab - for (int i = 0; i < pr->nconst; i++) { - // look if the bvalue pair is already in ktab - int found = 0; - for (int j = 0; j < ktab_size; j++) { - // to avoid any size issue, we compare all bytes - // berry_log_C("// p1=%p p2=%p sz=%i", &pr->ktab[i], &ktab[j], sizeof(bvalue)); - if ((pr->ktab[i].type == ktab[j].type) && (pr->ktab[i].v.i == ktab[j].v.i) && (pr->ktab[i].v.c == ktab[j].v.c)) { - // if (memcmp(&pr->ktab[i], &ktab[j], sizeof(bvalue)) == 0) { - found = 1; - break; - } - } - // if not already there, add it - if (!found) { - ktab[ktab_size++] = pr->ktab[i]; - } - if (ktab_size >= MAX_KTAB_SIZE) { - logfmt("// ktab too big for class '%s' - skipping\n", classname); - return; - } - } - ktab_total += pr->nconst; - } - } - - if (ktab_size == ktab_total) { - return; /* nothing to optimize, can happen for classes with zero or 1 method */ - } - /* allocate a proper ktab */ - bvalue *new_ktab = be_malloc(vm, sizeof(bvalue) * ktab_size); - memmove(new_ktab, ktab, sizeof(bvalue) * ktab_size); - - /* second iteration to replace ktab and patch code */ - iter = be_map_iter(); - while ((node = be_map_next(cla->members, &iter)) != NULL) { - if (var_isstr(&node->key) && var_isclosure(&node->value)) { - bclosure *cl = var_toobj(&node->value); - bproto *pr = cl->proto; - - if ((gc_isconst(cl)) || (pr->varg & BE_VA_SHARED_KTAB) || (pr->varg & BE_VA_NOCOMPACT)) { continue; } - - uint8_t mapping_array[MAX_KTAB_SIZE]; - // iterate in proto ktab to get the index in the global ktab - for (int i = 0; i < pr->nconst; i++) { - for (int j = 0; j < ktab_size; j++) { - // compare all bytes - if ((pr->ktab[i].type == ktab[j].type) && (pr->ktab[i].v.i == ktab[j].v.i) && (pr->ktab[i].v.c == ktab[j].v.c)) { - // if (memcmp(&pr->ktab[i], &ktab[j], sizeof(bvalue)) == 0) { - mapping_array[i] = j; - break; - } - } - } - - // replace ktab - pr->ktab = new_ktab; - pr->nconst = ktab_size; - // flag as shared ktab - pr->varg |= BE_VA_SHARED_KTAB; - // parse code to replace any K reference - for (int pc = 0; pc < pr->codesize; pc++) { - uint32_t ins = pr->code[pc]; - bopcode op = IGET_OP(ins); - - /* handle all impacted opcodes */ - /* Possibilities: */ - /* "B" | "B and C" | "Bx" contain a constant code */ - /* special case for OP_RET where "B" may not contain anything */ - switch (op) { - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: - case OP_MOD: case OP_LT: case OP_LE: case OP_EQ: - case OP_NE: case OP_GT: case OP_GE: case OP_CONNECT: - case OP_GETMBR: case OP_SETMBR: case OP_GETMET: - case OP_GETIDX: case OP_SETIDX: case OP_AND: - case OP_OR: case OP_XOR: case OP_SHL: case OP_SHR: - case OP_RAISE: - // B and C might contain 'K' constant - if (isKB(ins)) { - int kidx = IGET_RKB(ins) & KR_MASK; - if (kidx >= ktab_size) { - be_raise(vm, "value_error", "invalid ktab index"); - } - ins = (ins & ~IRKB_MASK) | ISET_RKB(setK(mapping_array[kidx])); - } - if (isKC(ins)) { - int kidx = IGET_RKC(ins) & KR_MASK; - if (kidx >= ktab_size) { - be_raise(vm, "value_error", "invalid ktab index"); - } - ins = (ins & ~IRKC_MASK) | ISET_RKC(setK(mapping_array[kidx])); - } - pr->code[pc] = ins; - break; - case OP_MOVE: case OP_SETSUPER: case OP_NEG: case OP_FLIP: case OP_IMPORT: - case OP_GETNGBL: case OP_SETNGBL: - // Only B might contain 'K' constant - if (isKB(ins)) { - int kidx = IGET_RKB(ins) & KR_MASK; - if (kidx >= ktab_size) { - be_raise(vm, "value_error", "invalid ktab index"); - } - ins = (ins & ~IRKB_MASK) | ISET_RKB(setK(mapping_array[kidx])); - } - pr->code[pc] = ins; - break; - case OP_CLASS: - case OP_LDCONST: - // Bx contains the K - { - int kidx = IGET_Bx(ins); - if (kidx >= ktab_size) { - be_raise(vm, "value_error", "invalid ktab index"); - } - ins = (ins & ~IBx_MASK) | ISET_Bx(mapping_array[kidx]); - pr->code[pc] = ins; - } - break; - case OP_RET: - if (IGET_RA(ins)) { - // Only B might contain 'K' constant - if (isKB(ins)) { - int kidx = IGET_RKB(ins) & KR_MASK; - if (kidx >= ktab_size) { - be_raise(vm, "value_error", "invalid ktab index"); - } - ins = (ins & ~IRKB_MASK) | ISET_RKB(setK(mapping_array[kidx])); - } - } - pr->code[pc] = ins; - break; - /* The following opcodes are not impacted by shared constant table - case OP_GETUPV: case OP_SETUPV: - case OP_LDCONST: - case OP_CALL: - case OP_CLOSURE: - case OP_CLOSE: case OP_LDNIL: - case OP_EXBLK: - case OP_CATCH: - case OP_GETGBL: case OP_SETGBL: - case OP_JMP: - case OP_JMPT: case OP_JMPF: - case OP_LDINT: - case OP_LDBOOL: */ - default: - break; - } - - } - } - } - } - // logfmt("extern const bclass be_class_%s;\n", classname); - // scan classes and generate extern statements for classes - for (int k = 0; k < ktab_size; k++) { - // if it's a class, print an extern statement - if (var_isclass(&ktab[k])) { - bclass *cl = var_toobj(&ktab[k]); - logfmt("extern const bclass be_class_%s;\n", str(cl->name)); - } - } - - // scan again to export all sub-classes - for (int k = 0; k < ktab_size; k++) { - // if it's a class, print an extern statement - if (var_isclass(&ktab[k])) { - bclass *cl = var_toobj(&ktab[k]); - if (cl != cla) { - m_solidify_subclass(vm, str_literal, cl, fout); - } - } - } - - // output shared ktab - int indent = 0; - logfmt("// compact class '%s' ktab size: %d, total: %d (saved %i bytes)\n", classname, ktab_size, ktab_total, (ktab_total - ktab_size) * 8); - logfmt("static const bvalue be_ktab_class_%s[%i] = {\n", classname, ktab_size); - for (int k = 0; k < ktab_size; k++) { - logfmt("%*s/* K%-3d */ ", indent + 2, "", k); - m_solidify_bvalue(vm, str_literal, &ktab[k], NULL, NULL, fout); - logfmt(",\n"); - } - logfmt("%*s};\n", indent, ""); - logfmt("\n"); -} - -// takes a class or a module -// scans all first level bproto -// build a consolidated 'ktab' array -// check that the array is not bigger than 256 (which is the max acceptable constants) -// (for now) print the potential saving -static int m_compact(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - bbool str_literal = bfalse; - if (top >= 2) { - str_literal = be_tobool(vm, 2); - } - void* fout = NULL; /* output file */ - if (top >= 3 && be_isinstance(vm, 3)) { - be_getmember(vm, 3, ".p"); - if (be_iscomptr(vm, -1)) { - fout = be_tocomptr(vm, -1); - } - be_pop(vm, 1); - } - // const char *prefix_name = NULL; /* allow to specify an explicit prefix */ - // if (top >= 4 && be_isstring(vm, 4)) { - // prefix_name = be_tostring(vm, 4); - // } - if (var_isclass(v)) { - m_compact_class(vm, str_literal, var_toobj(v), fout); - } else if (var_ismodule(v)) { - // TODO - } else { - be_raise(vm, "value_error", "unsupported type"); - } - } - be_return_nil(vm); -} - -static int m_nocompact(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1) { - bvalue *v = be_indexof(vm, 1); - if (var_isclosure(v)) { - bclosure *cl = var_toobj(v); - bproto *pr = cl->proto; - pr->varg |= BE_VA_NOCOMPACT; - } else { - be_raise(vm, "value_error", "unsupported type"); - } - } - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(solidify) { - be_native_module_function("dump", m_dump), - be_native_module_function("compact", m_compact), -}; - -be_define_native_module(solidify, NULL); -#else -/* @const_object_info_begin -module solidify (scope: global, depend: BE_USE_SOLIDIFY_MODULE) { - dump, func(m_dump) - compact, func(m_compact) - nocompact, func(m_nocompact) -} -@const_object_info_end */ -#include "../generate/be_fixed_solidify.h" -#endif - -#endif /* BE_USE_SOLIFIDY_MODULE */ diff --git a/lib/libesp32/Berry/src/be_strictlib.c b/lib/libesp32/Berry/src/be_strictlib.c deleted file mode 100644 index b40329886187..000000000000 --- a/lib/libesp32/Berry/src/be_strictlib.c +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2021 Guan Wenliang & Stephan Hadinger -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" -#include "be_module.h" -#include "be_string.h" -#include "be_vector.h" -#include "be_class.h" -#include "be_debug.h" -#include "be_map.h" -#include "be_vm.h" - -#if BE_USE_STRICT_MODULE - -static int m_init(bvm *vm) -{ - comp_set_strict(vm); /* enable compiler strict mode */ - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(strict) { - be_native_module_function("init", m_init), -}; - -be_define_native_module(strict, NULL); -#else -/* @const_object_info_begin -module strict (scope: strict, depend: BE_USE_STRICT_MODULE) { - init, func(m_init) -} -@const_object_info_end */ -#include "../generate/be_fixed_strict.h" -#endif - -#endif /* BE_USE_STRICT_MODULE */ diff --git a/lib/libesp32/Berry/src/be_string.c b/lib/libesp32/Berry/src/be_string.c deleted file mode 100644 index 806e37ff0c8a..000000000000 --- a/lib/libesp32/Berry/src/be_string.c +++ /dev/null @@ -1,326 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_string.h" -#include "be_vm.h" -#include "be_mem.h" -#include "be_constobj.h" -#include - -#define next(_s) cast(void*, cast(bstring*, (_s)->next)) -#define sstr(_s) cast(char*, cast(bsstring*, _s) + 1) -#define lstr(_s) cast(char*, cast(blstring*, _s) + 1) -#define cstr(_s) (cast(bcstring*, _s)->s) - -#define be_define_const_str(_name, _s, _hash, _extra, _len, _next) \ - BERRY_LOCAL const bcstring be_const_str_##_name = { \ - .next = (bgcobject *)_next, \ - .type = BE_STRING, \ - .marked = GC_CONST, \ - .extra = _extra, \ - .slen = _len, \ - .hash = _hash, \ - .s = _s \ - } - -#define be_define_const_str_long(_name, _s, _len) \ - BERRY_LOCAL const bclstring be_const_str_##_name = { \ - .next = (bgcobject *)NULL, \ - .type = BE_STRING, \ - .marked = GC_CONST, \ - .extra = 0, \ - .slen = 255, \ - .llen = _len, \ - .s = _s \ - } - -/* const string table */ -struct bconststrtab { - const bstring* const *table; - int count; /* string count */ - int size; -}; - -#if BE_USE_PRECOMPILED_OBJECT -#include "../generate/be_const_strtab_def.h" -#endif - -int be_eqstr(bstring *s1, bstring *s2) -{ - int slen; - if (s1 == s2) { /* short string or the same string */ - return 1; - } - slen = s1->slen; - /* discard different lengths */ - if (slen != s2->slen) { - return 0; - } - /* long string */ - if (slen == 255) { /* s2->slen is also 255 */ - blstring *ls1 = cast(blstring*, s1); - blstring *ls2 = cast(blstring*, s2); - return ls1->llen == ls2->llen && !strcmp(lstr(ls1), lstr(ls2)); - } - /* const short strings */ - if (gc_isconst(s1) || gc_isconst(s2)) { /* one of the two string is short const */ - uint32_t hash1 = cast(bcstring*, s1)->hash; - uint32_t hash2 = cast(bcstring*, s2)->hash; - if (hash1 && hash2 && hash1 != hash2) { - return 0; /* if hash differ, since we know both are non-null */ - } - /* if hash are equals, there might be a chance that they are different */ - /* This can happen with solidified code that a same string is present more than once */ - /* so just considering that two strings with the same hash must be same pointer, this is no more true */ - return !strcmp(str(s1), str(s2)); - } - - /* if both strings are in-memory, they can't be equal without having the same pointer */ - return 0; -} - -static void resize(bvm *vm, int size) -{ - int i; - struct bstringtable *tab = &vm->strtab; - if (size > tab->size) { - tab->table = be_realloc(vm, tab->table, - tab->size * sizeof(bstring*), size * sizeof(bstring*)); - for (i = tab->size; i < size; ++i) { - tab->table[i] = NULL; - } - } - for (i = 0; i < tab->size; ++i) { /* rehash */ - bstring *p = tab->table[i]; - tab->table[i] = NULL; - while (p) { /* for each node in the list */ - bstring *hnext = next(p); - uint32_t hash = be_strhash(p) & (size - 1); - p->next = cast(void*, tab->table[hash]); - tab->table[hash] = p; - p = hnext; - } - } - if (size < tab->size) { - for (i = size; i < tab->size; ++i) { - tab->table[i] = NULL; - } - tab->table = be_realloc(vm, tab->table, - tab->size * sizeof(bstring*), size * sizeof(bstring*)); - } - tab->size = size; -} - -static void free_sstring(bvm *vm, bstring *str) -{ - be_free(vm, str, sizeof(bsstring) + str->slen + 1); -} - -/* FNV-1a Hash */ -static uint32_t str_hash(const char *str, size_t len) -{ - uint32_t hash = 2166136261u; - be_assert(str || !len); - while (len--) { - hash = (hash ^ (unsigned char)*str++) * 16777619u; - } - return hash; -} - -void be_string_init(bvm *vm) -{ - resize(vm, 8); -#if !BE_USE_PRECOMPILED_OBJECT - /* the destructor name deinit needs to exist all the time, to ensure - * that it does not need to be created when the heap is exhausted. */ - be_gc_fix(vm, cast(bgcobject*, str_literal(vm, "deinit"))); -#endif - /* be_const_str_deinit --> for precompiled */ -} - -void be_string_deleteall(bvm *vm) -{ - int i; - struct bstringtable *tab = &vm->strtab; - for (i = 0; i < tab->size; ++i) { - bstring *node = tab->table[i]; - while (node) { - bstring *next = next(node); - free_sstring(vm, node); - node = next; - } - } - be_free(vm, tab->table, tab->size * sizeof(bstring*)); -} - -static bstring* createstrobj(bvm *vm, size_t len, int islong) -{ - size_t size = (islong ? sizeof(blstring) - : sizeof(bsstring)) + len + 1; - bgcobject *gco = be_gc_newstr(vm, size, islong); - bstring *s = cast_str(gco); - if (s) { - s->slen = islong ? 255 : (bbyte)len; - char *str = cast(char *, islong ? lstr(s) : sstr(s)); - str[len] = '\0'; - } - return s; -} - -#if BE_USE_PRECOMPILED_OBJECT -static bstring* find_conststr(const char *str, size_t len) -{ - const struct bconststrtab *tab = &m_const_string_table; - uint32_t hash = str_hash(str, len); - bcstring *s = (bcstring*)tab->table[hash % tab->size]; - for (; s != NULL; s = next(s)) { - if (len == 0 && s->slen == 0) { - /* special case for the empty string, - since we don't want to compare it using strncmp, - because str might be NULL */ - return (bstring*)s; - } - if (len == s->slen && !strncmp(str, s->s, len)) { - return (bstring*)s; - } - } - return NULL; -} -#endif - -static bstring* newshortstr(bvm *vm, const char *str, size_t len) -{ - bstring *s; - int size = vm->strtab.size; - uint32_t hash = str_hash(str, len); - bstring **list = vm->strtab.table + (hash & (size - 1)); - - for (s = *list; s != NULL; s = next(s)) { - if (len == s->slen && !strncmp(str, sstr(s), len)) { - return s; - } - } - s = createstrobj(vm, len, 0); - if (s) { - /* recompute size and list that may have changed due to a GC */ - size = vm->strtab.size; - list = vm->strtab.table + (hash & (size - 1)); - memcpy(cast(char *, sstr(s)), str, len); - s->extra = 0; - s->next = cast(void*, *list); -#if BE_USE_STR_HASH_CACHE - cast(bsstring*, s)->hash = hash; -#endif - *list = s; - vm->strtab.count++; - if (vm->strtab.count > size << 2) { - resize(vm, size << 1); - } - } - return s; -} - -bstring* be_newlongstr(bvm *vm, const char *str, size_t len) -{ - bstring *s; - blstring *ls; - s = createstrobj(vm, len, 1); - ls = cast(blstring*, s); - s->extra = 0; - ls->llen = cast_int(len); - if (str) { /* if the argument 'str' is NULL, we just allocate space */ - memcpy(cast(char *, lstr(s)), str, len); - } - return s; -} - -bstring* be_newstr(bvm *vm, const char *str) -{ - return be_newstrn(vm, str, strlen(str)); -} - -bstring *be_newstrn(bvm *vm, const char *str, size_t len) -{ - if (len <= SHORT_STR_MAX_LEN) { -#if BE_USE_PRECOMPILED_OBJECT - bstring *s = find_conststr(str, len); - return s ? s : newshortstr(vm, str, len); -#else - return newshortstr(vm, str, len); -#endif - } - return be_newlongstr(vm, str, len); /* long string */ -} - -void be_gcstrtab(bvm *vm) -{ - struct bstringtable *tab = &vm->strtab; - int size = tab->size, i; - for (i = 0; i < size; ++i) { - bstring **list = tab->table + i; - bstring *prev = NULL, *node, *next; - for (node = *list; node; node = next) { - next = next(node); - if (!gc_isfixed(node) && gc_iswhite(node)) { - free_sstring(vm, node); - tab->count--; - if (prev) { /* link list */ - prev->next = cast(void*, next); - } else { - *list = next; - } - } else { - prev = node; - gc_setwhite(node); - } - } - } - if (BE_USE_DEBUG_GC || comp_is_gc_debug(vm)) { - resize(vm, tab->count + 4); - } else { - if (tab->count < size >> 2 && size > 8) { - resize(vm, size >> 1); - } - } -} - -uint32_t be_strhash(const bstring *s) -{ - if (gc_isconst(s) && (s->slen != 255)) { - bcstring* cs = cast(bcstring*, s); - if (cs->hash) { /* if hash is null we need to compute it */ - return cs->hash; - } else { - return str_hash(cstr(s), str_len(s)); - } - } -#if BE_USE_STR_HASH_CACHE - if (s->slen != 255) { - return cast(bsstring*, s)->hash; - } -#endif - return str_hash(str(s), str_len(s)); -} - -const char* be_str2cstr(const bstring *s) -{ - be_assert(cast_str(s) != NULL); - if (s->slen == 255) { - return lstr(s); - } - if (gc_isconst(s)) { - return cstr(s); - } - return sstr(s); -} - -void be_str_setextra(bstring *s, int extra) -{ - if (!gc_isconst(s)) { - s->extra = cast(bbyte, extra); - } -} diff --git a/lib/libesp32/Berry/src/be_string.h b/lib/libesp32/Berry/src/be_string.h deleted file mode 100644 index f39ae6c4f438..000000000000 --- a/lib/libesp32/Berry/src/be_string.h +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_STRING_H -#define BE_STRING_H - -#include "be_object.h" - -#define SHORT_STR_MAX_LEN 64 - -typedef struct { - bstring_header; -#if BE_USE_STR_HASH_CACHE - uint32_t hash; -#endif - /* char s[]; */ -} bsstring; - -typedef struct { - bstring str; - int llen; - /* char s[]; */ -} blstring; - -typedef struct { /* const long string */ - bstring_header; - int llen; - char s[]; -} bclstring; - -typedef struct { - bstring_header; - uint32_t hash; - const char *s; -} bcstring; - -#define str_len(_s) \ - ((_s)->slen == 255 ? cast(blstring*, _s)->llen : (_s)->slen) - -#define str(_s) be_str2cstr(_s) -#define str_extra(_s) ((_s)->extra) -#define str_literal(_vm, _s) be_newstrn((_vm), (_s), sizeof(_s) - 1) - -#if BE_USE_PRECOMPILED_OBJECT -#include "../generate/be_const_strtab.h" -#endif - -void be_string_init(bvm *vm); -void be_string_deleteall(bvm *vm); -int be_eqstr(bstring *s1, bstring *s2); -bstring* be_newstr(bvm *vm, const char *str); -bstring* be_newstrn(bvm *vm, const char *str, size_t len); -bstring* be_newlongstr(bvm *vm, const char *str, size_t len); -void be_gcstrtab(bvm *vm); -uint32_t be_strhash(const bstring *s); -const char* be_str2cstr(const bstring *s); -void be_str_setextra(bstring *s, int extra); - -#endif diff --git a/lib/libesp32/Berry/src/be_strlib.c b/lib/libesp32/Berry/src/be_strlib.c deleted file mode 100644 index 2ce560910926..000000000000 --- a/lib/libesp32/Berry/src/be_strlib.c +++ /dev/null @@ -1,1069 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_strlib.h" -#include "be_string.h" -#include "be_vm.h" -#include "be_class.h" -#include "be_module.h" -#include "be_exec.h" -#include "be_mem.h" -#include "be_baselib.h" -#include -#include -#include - -#define is_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n') -#define is_digit(c) ((c) >= '0' && (c) <= '9') -#define skip_space(s) while (is_space(*(s))) { ++(s); } - -static int str_strncasecmp(const char *s1, const char *s2, size_t n) -{ - if (n == 0) return 0; - - while (n-- != 0 && tolower(*s1) == tolower(*s2)) { - if (n == 0 || *s1 == '\0' || *s2 == '\0') - break; - s1++; - s2++; - } - - return tolower(*(const unsigned char *)s1) - - tolower(*(const unsigned char *)s2); -} - -typedef bint (*str_opfunc)(const char*, const char*, bint, bint); - -bstring* be_strcat(bvm *vm, bstring *s1, bstring *s2) -{ - size_t len = (size_t)str_len(s1) + str_len(s2); - if (len <= SHORT_STR_MAX_LEN) { - char buf[SHORT_STR_MAX_LEN + 1]; - strcpy(buf, str(s1)); - strncat(buf, str(s2), len); - return be_newstrn(vm, buf, len); - } else { /* long string */ - bstring *s = be_newstrn(vm, NULL, len); - char *sbuf = (char*)str(s); - strcpy(sbuf, str(s1)); - strcpy(sbuf + str_len(s1), str(s2)); - return s; - } -} - -int be_strcmp(bstring *s1, bstring *s2) -{ - if (be_eqstr(s1, s2)) { - return 0; - } - return strcmp(str(s1), str(s2)); -} - -bstring* be_num2str(bvm *vm, bvalue *v) -{ - char buf[25]; - if (var_isint(v)) { - snprintf(buf, sizeof(buf),BE_INT_FORMAT, var_toint(v)); - } else if (var_isreal(v)) { - snprintf(buf, sizeof(buf), "%g", var_toreal(v)); - } else { - snprintf(buf, sizeof(buf), "(nan)"); - } - return be_newstr(vm, buf); -} - -static void module2str(char *buf, size_t buf_len, bvalue *v) -{ - const char *name = be_module_name(cast(bmodule*, var_toobj(v))); - if (name) { - snprintf(buf, buf_len, "", name); - } else { - snprintf(buf, buf_len, "", var_toobj(v)); - } -} - -static bstring* sim2str(bvm *vm, bvalue *v) -{ - char sbuf[64]; /* BUG: memory overflow */ - switch (var_type(v)) { - case BE_NIL: - strcpy(sbuf, "nil"); - break; - case BE_BOOL: - strcpy(sbuf, var_tobool(v) ? "true" : "false"); - break; - case BE_INDEX: - case BE_INT: - snprintf(sbuf, sizeof(sbuf), BE_INT_FORMAT, var_toint(v)); - break; - case BE_REAL: - snprintf(sbuf, sizeof(sbuf), "%g", var_toreal(v)); - break; - case BE_CLOSURE: case BE_NTVCLOS: case BE_NTVFUNC: case BE_CTYPE_FUNC: - snprintf(sbuf, sizeof(sbuf), "", var_toobj(v)); - break; - case BE_CLASS: - snprintf(sbuf, sizeof(sbuf), "", - str(be_class_name(cast(bclass*, var_toobj(v))))); - break; - case BE_MODULE: - module2str(sbuf, sizeof(sbuf), v); - break; - case BE_COMPTR: - snprintf(sbuf, sizeof(sbuf), "", var_toobj(v)); - break; - default: - strncpy(sbuf, "(unknown value)", sizeof(sbuf)); - break; - } - return be_newstr(vm, sbuf); -} - -static bstring* ins2str(bvm *vm, int idx) -{ - bstring *s = str_literal(vm, "tostring"); - binstance *obj = var_toobj(vm->reg + idx); - /* get method 'tostring' */ - int type = be_instance_member(vm, obj, s, vm->top); - be_incrtop(vm); /* push the obj::tostring to stack */ - if (basetype(type) != BE_FUNCTION) { - bstring *name = be_class_name(be_instance_class(obj)); - size_t buf_len = (size_t) str_len(name) + 16; - char *sbuf = be_malloc(vm, buf_len); - /* TODO what if sbuf cannot be allocated */ - snprintf(sbuf, buf_len, "", str(name)); - be_stackpop(vm, 1); /* pop the obj::tostring */ - s = be_newstr(vm, sbuf); - be_free(vm, sbuf, (size_t)str_len(name) + 16); - } else { - *vm->top = vm->reg[idx]; - be_dofunc(vm, vm->top - 1, 1); - be_stackpop(vm, 1); /* pop the obj::tostring */ - if (!var_isstr(vm->top)) { /* check the return value */ - const char *name = str(be_instance_name(obj)); - be_raise(vm, "runtime_error", be_pushfstring(vm, - "the value of `%s::tostring()` is not a 'string'", - strlen(name) ? name : "")); - } - s = var_tostr(vm->top); - } - return s; -} - -void be_val2str(bvm *vm, int index) -{ - bstring *s; - int idx = be_absindex(vm, index) - 1; - bvalue *v = vm->reg + idx; - if (var_isstr(v)) return; /* do nothing */ - s = var_isinstance(v) ? ins2str(vm, idx) : sim2str(vm, v); - v = vm->reg + idx; /* the stack may change */ - var_setstr(v, s); -} - -static void pushstr(bvm *vm, const char *s, size_t len) -{ - /* to create a string and then update the top pointer, - * otherwise the GC may crash due to uninitialized values. - **/ - bstring *str = be_newstrn(vm, s, len); - bvalue *reg = be_incrtop(vm); - var_setstr(reg, str); -} - -static const char* concat2(bvm *vm) -{ - bvalue *dst = vm->top - 2; - bstring *s1 = var_tostr(dst); - bstring *s2 = var_tostr(dst + 1); - bstring *s = be_strcat(vm, s1, s2); - be_assert(var_isstr(vm->top - 2) && var_isstr(vm->top - 1)); - dst = vm->top - 2; /* the stack may change */ - var_setstr(dst, s); - --vm->top; - return str(s); -} - -const char* be_pushvfstr(bvm *vm, const char *format, va_list arg) -{ - pushstr(vm, "", 0); - for (;;) { - const char *p = strchr(format, '%'); - if (p == NULL) { - break; - } - pushstr(vm, format, p - format); - concat2(vm); - switch (p[1]) { - case 's': { - const char *s = va_arg(arg, char*); - if (s == NULL) { - s = "(null)"; - } - pushstr(vm, s, strlen(s)); - break; - } - case 'd': { - bstring *s; - bvalue *v = be_incrtop(vm); - var_setint(v, va_arg(arg, int)); - s = be_num2str(vm, v); - var_setstr(v, s); - break; - } - case 'f': case 'g': { - bstring *s; - bvalue *v = be_incrtop(vm); - var_setreal(v, cast(breal, va_arg(arg, double))); - s = be_num2str(vm, v); - var_setstr(v, s); - break; - } - case 'c': { - char c = cast(char, va_arg(arg, int)); - pushstr(vm, &c, 1); - break; - } - case '%': { - pushstr(vm, "%", 1); - break; - } - case 'p': { - char buf[2 * sizeof(void*) + 4]; - snprintf(buf, sizeof(buf), "%p", va_arg(arg, void*)); - pushstr(vm, buf, strlen(buf)); - break; - } - default: - pushstr(vm, "(unknown)", 8); - break; - } - concat2(vm); - format = p + 2; - } - pushstr(vm, format, strlen(format)); - return concat2(vm); -} - -int be_char2hex(int c) -{ - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 0x0A; - } else if (c >= 'A' && c <= 'F') { - return c - 'A' + 0x0A; - } - return -1; -} - -/******************************************************************* - * the function be_str2int(): - * >>-+------------+--+--+-----+----digits-------+---------------->< - * '-whitespace-' | +- + -+ | - * | '- - -' | - * | | - * +- 0x or 0X ---hex_digits--+ - * - *******************************************************************/ -BERRY_API bint be_str2int(const char *str, const char **endstr) -{ - int c, sign; - bint sum = 0; - skip_space(str); - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { - /* hex literal */ - str += 2; /* skip 0x or 0X */ - while ((c = be_char2hex(*str++)) >= 0) { - sum = sum * 16 + c; - } - if (endstr) { - *endstr = str - 1; - } - return sum; - } else { - /* decimal literal */ - sign = c = *str++; - if (c == '+' || c == '-') { - c = *str++; - } - while (is_digit(c)) { - sum = sum * 10 + c - '0'; - c = *str++; - } - if (endstr) { - *endstr = str - 1; - } - return sign == '-' ? -sum : sum; - } -} - -/******************************************************************* - * the function be_str2real(): - * >>-+------------+--+-----+--+-digits--+---+--+--------+-+-------> - * '-whitespace-' +- + -+ | '-.-' '-digits-' | - * '- - -' '-.--digits-----------------' - * - * >--+------------------------+---------------------------------->< - * '-+-e-+--+-----+--digits-' - * '-E-' +- + -+ - * '- - -' - *******************************************************************/ -BERRY_API breal be_str2real(const char *str, const char **endstr) -{ - int c, sign; - breal sum = 0, deci = 0, point = (breal)0.1; - skip_space(str); - sign = c = *str++; - if (c == '+' || c == '-') { - c = *str++; - } - while (is_digit(c)) { - sum = sum * 10 + c - '0'; - c = *str++; - } - if (c == '.') { - c = *str++; - while (is_digit(c)) { - deci = deci + ((breal)c - '0') * point; - point *= (breal)0.1; - c = *str++; - } - } - sum = sum + deci; - if (c == 'e' || c == 'E') { - int e = 0; - breal ratio = (c = *str++) == '-' ? (breal)0.1 : 10; - if (c == '+' || c == '-') { - c = *str++; - } - while (is_digit(c)) { - e = e * 10 + c - '0'; - c = *str++; - } - while (e--) { - sum *= ratio; - } - } - if (endstr) { - *endstr = str - 1; - } - return sign == '-' ? -sum : sum; -} - -/* convert a string to a number (integer or real). - * 1. skip \s*[\+\-]?\d* - * 2. matched [.eE]? yes: real, no: integer. - **/ -BERRY_API const char *be_str2num(bvm *vm, const char *str) -{ - const char *sout; - bint c, vint = be_str2int(str, &sout); - c = *sout; - if (c == '.' || c == 'e' || c == 'E') { - be_pushreal(vm, be_str2real(str, &sout)); - } else { - be_pushint(vm, vint); - } - return sout; -} - -static bstring* string_range(bvm *vm, bstring *str, binstance *range) -{ - bint lower, upper; - bint size = str_len(str); /* size of source string */ - /* get index range */ - bvalue temp; - be_instance_member(vm, range, be_newstr(vm, "__lower__"), &temp); - lower = var_toint(&temp); - be_instance_member(vm, range, be_newstr(vm, "__upper__"), &temp); - upper = var_toint(&temp); - /* protection scope */ - if (upper < 0) { upper = size + upper; } - if (lower < 0) { lower = size + lower; } - upper = upper < size ? upper : size - 1; - lower = lower < 0 ? 0 : lower; - if (lower > upper) { - return be_newstrn(vm, "", 0); /* empty string */ - } - return be_newstrn(vm, str(str) + lower, upper - lower + 1); - -} - -/* string subscript operation */ -bstring* be_strindex(bvm *vm, bstring *str, bvalue *idx) -{ - if (var_isint(idx)) { - int pos = var_toidx(idx); - int size = str_len(str); - if (pos < 0) { pos = size + pos; } - if ((pos < size) && (pos >= 0)) { - return be_newstrn(vm, str(str) + pos, 1); - } - be_raise(vm, "index_error", "string index out of range"); - } else if (var_isinstance(idx)) { - binstance * ins = var_toobj(idx); - const char *cname = str(be_instance_name(ins)); - if (!strcmp(cname, "range")) { - return string_range(vm, str, ins); - } - // str(be_instance_name(i)) - } - be_raise(vm, "index_error", "string indices must be integers"); - return NULL; -} - -size_t be_strlcpy(char *dst, const char *src, size_t maxlen) -{ - const size_t srclen = strlen(src); - if (srclen + 1 < maxlen) { - memcpy(dst, src, srclen + 1); - } else if (maxlen != 0) { - memcpy(dst, src, maxlen - 1); - dst[maxlen-1] = '\0'; - } - return srclen; -} - -const char* be_splitpath(const char *path) -{ - const char *p; - for (p = path - 1; *path != '\0'; ++path) { - if (*path == '/') { - p = path; - } - } - return p + 1; /* return the file name pointer */ -} - -const char* be_splitname(const char *path) -{ - const char *p, *q, *end = path + strlen(path); - for (p = end; *p != '.' && p > path; --p); /* skip [^\.] */ - for (q = p; *q == '.' && q > path; --q); /* skip \. */ - if ((q == path && *q == '.') || *q == '/') { - return end; - } - return p; -} - -static unsigned escape_length(const char *s, int quote) -{ - unsigned c, len = 0, step = quote == '"' ? 5 : 3; - for (; (c = *s) != '\0'; ++s) { - switch (c) { - case '\\': case '\n': case '\r': case '\t': - len += 1; - break; - default: - if (c < 0x20) - len += step; - else if (c == (unsigned)quote) - len += 1; - break; - } - } - return len; -} - -static unsigned eschex(unsigned num) -{ - return num <= 9 ? '0' + num : 'a' + num - 10; -} - -/* escape as Berry or JSON */ -static char* escape(char *q, unsigned c, int quote) -{ - int json = quote == '"'; - switch (c) { - case '\\': *q++ = '\\'; *q = '\\'; break; - case '\n': *q++ = '\\'; *q = 'n'; break; - case '\r': *q++ = '\\'; *q = 'r'; break; - case '\t': *q++ = '\\'; *q = 't'; break; - default: - if (c < 0x20) { /* other characters are escaped using '\uxxxx' */ - *q++ = '\\'; - if (json) { - *q++ = 'u'; *q++ = '0'; *q++ = '0'; - *q++ = (char)eschex(c >> 4); - *q = (char)eschex(c & 0x0f); - } else { - *q++ = 'x'; - *q++ = (char)eschex(c >> 4); - *q = (char)eschex(c & 0x0f); - } - } else { /* quotes and unescaped characters */ - if (c == (unsigned)quote) - *q++ = '\\'; - *q = (char)c; - } - break; - } - return q; -} - -static void toescape(bvm *vm, int index, int quote) -{ - char *buf, *q; - const char *p, *s = be_tostring(vm, index); - size_t len = (size_t)be_strlen(vm, index); - len += escape_length(s, quote) + 2; /* escape length + quote mark */ - buf = q = be_pushbuffer(vm, len); - *q++ = (char)quote; /* add first quote */ - /* generate escape string */ - for (p = s; *p != '\0'; ++p, ++q) { - q = escape(q, *p, quote); - } - *q = (char)quote; /* add last quote */ - be_pushnstring(vm, buf, len); /* make escape string from buffer */ - be_moveto(vm, -1, index); - be_pop(vm, 2); /* remove buffer & top string */ -} - -BERRY_API const char* be_toescape(bvm *vm, int index, int mode) -{ - if (be_isstring(vm, index)) { - index = be_absindex(vm, index); - toescape(vm, index, mode == 'u' ? '"' : '\''); - } - return be_tostring(vm, index); -} - -#if BE_USE_STRING_MODULE - -#define MAX_FORMAT_MODE 32 -#define FLAGES "+- #0" - -static const char* skip2dig(const char *s) -{ - if (is_digit(*s)) { - ++s; - } - if (is_digit(*s)) { - ++s; - } - return s; -} - -static const char* get_mode(const char *str, char *buf, size_t buf_len) -{ - const char *p = str; - while (*p && strchr(FLAGES, *p)) { /* skip flags */ - ++p; - } - p = skip2dig(p); /* skip width (2 digits at most) */ - if (*p == '.') { - p = skip2dig(++p); /* skip width (2 digits at most) */ - } - *(buf++) = '%'; - size_t mode_size = p - str + 1; - /* Leave 2 bytes for the leading % and the trailing '\0' */ - if (mode_size > buf_len - 2) { - mode_size = buf_len - 2; - } - strncpy(buf, str, mode_size); - buf[mode_size] = '\0'; - return p; -} - -static void mode_fixlen(char *mode, const char *lenmode) -{ - size_t l = strlen(mode), lm = strlen(lenmode); - char spec = mode[l - 1]; - strcpy(mode + l - 1, lenmode); - mode[l + lm - 1] = spec; - mode[l + lm] = '\0'; -} - -static bbool convert_to_int(bvm *vm, int index, bint *val) -{ - bbool converted = bfalse; - if (val == NULL) { return bfalse; } - if (be_isint(vm, index)) { - *val = be_toint(vm, index); - converted = btrue; - } else { - be_pushntvfunction(vm, be_baselib_int); - be_pushvalue(vm, index); - be_call(vm, 1); - be_pop(vm, 1); - if (be_isint(vm, -1)) { - *val = be_toint(vm, -1); - converted = btrue; - } - be_pop(vm, 1); - } - return converted; -} - -static bbool convert_to_real(bvm *vm, int index, breal *val) -{ - bbool converted = bfalse; - if (val == NULL) { return bfalse; } - if (be_isnumber(vm, index)) { - *val = be_toreal(vm, index); - converted = btrue; - } else { - be_pushntvfunction(vm, be_baselib_real); - be_pushvalue(vm, index); - be_call(vm, 1); - be_pop(vm, 1); - if (be_isnumber(vm, -1)) { - *val = be_toreal(vm, -1); - converted = btrue; - } - be_pop(vm, 1); - } - return converted; -} - -int be_str_format(bvm *vm) -{ - int top = be_top(vm); - if (top > 0 && be_isstring(vm, 1)) { - int index = 2; - const char *format = be_tostring(vm, 1); - pushstr(vm, "", 0); - for (;;) { - char mode[MAX_FORMAT_MODE]; - char buf[128]; - const char *p = strchr(format, '%'); - if (p == NULL) { - break; - } - pushstr(vm, format, p - format); - concat2(vm); - p = get_mode(p + 1, mode, sizeof(mode)); - buf[0] = '\0'; - if (index > top && *p != '%') { - be_raise(vm, "runtime_error", be_pushfstring(vm, - "bad argument #%d to 'format': no value", index)); - } - switch (*p) { - case '%': - be_pushstring(vm, "%"); - --index; /* compensate the future ++index */ - break; - case 'd': case 'i': case 'o': - case 'u': case 'x': case 'X': - { - bint val; - if (convert_to_int(vm, index, &val)) { - mode_fixlen(mode, BE_INT_FMTLEN); - snprintf(buf, sizeof(buf), mode, val); - } - be_pushstring(vm, buf); - break; - } - case 'e': case 'E': - case 'f': case 'g': case 'G': - { - breal val; - if (convert_to_real(vm, index, &val)) { - snprintf(buf, sizeof(buf), mode, val); - } - be_pushstring(vm, buf); - break; - } - case 'c': - { - bint val; - if (convert_to_int(vm, index, &val)) { - snprintf(buf, sizeof(buf), "%c", (int)val); - } - be_pushstring(vm, buf); - break; - } - case 's': { - const char *s = be_tostring(vm, index); - int len = be_strlen(vm, index); - if (len > 100 && strlen(mode) == 2) { - be_pushvalue(vm, index); - } else { - snprintf(buf, sizeof(buf), mode, s); - be_pushstring(vm, buf); - } - break; - } - case 'q': { - const char *s = be_toescape(vm, index, 'q'); - int len = be_strlen(vm, index); - if (len > 100 && strlen(mode) == 2) { - be_pushvalue(vm, index); - } else { - snprintf(buf, sizeof(buf), "%s", s); - be_pushstring(vm, buf); - } - break; - } - default: /* error */ - be_raise(vm, "runtime_error", be_pushfstring(vm, - "invalid option '%%%c' to 'format'", *p)); - break; - } - concat2(vm); - format = p + 1; - ++index; - } - pushstr(vm, format, strlen(format)); - concat2(vm); - be_return(vm); - } - be_return_nil(vm); -} - -/* string.op(s1, s2, begin=0, end=length(s2)) */ -static bint str_operation(bvm *vm, str_opfunc func, bint error) -{ - int top = be_top(vm); - /* check the number and type of arguments */ - if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { - /* get the operation string and its length */ - int len1 = be_strlen(vm, 1); - int len2 = be_strlen(vm, 2); - const char *s1 = be_tostring(vm, 1); - const char *s2 = be_tostring(vm, 2); - /* get begin and end indexes (may use default values) */ - bint begin = top >= 3 && be_isint(vm, 3) ? be_toint(vm, 3) : 0; - bint end = top >= 4 && be_isint(vm, 4) ? be_toint(vm, 4) : len1; - /* basic range check: - * 1. begin position must be greater than 0 and - * less than the length of the source string. - * 2. the length of the pattern string cannot be - * less than the matching range (end - begin). - **/ - if (begin >= 0 && begin <= len1 && end - begin >= len2) { - /* call the operation function */ - return func(s1, s2, begin, end - len2); - } - } - return error; /* returns the default error value */ -} - -static bint _sfind(const char *s1, const char *s2, bint begin, bint end) -{ - const char *res = strstr(s1 + begin, s2); - if (res) { - bint pos = (bint)(res - s1); - return pos <= end ? pos : -1; - } - return -1; -} - -static int str_find(bvm *vm) -{ - be_pushint(vm, str_operation(vm, _sfind, -1)); - be_return(vm); -} - -static bint _scount(const char *s1, const char *s2, bint begin, bint end) -{ - bint count = 0; - const char *res = s1 + begin, *send = s1 + end; - while ((res = strstr(res, s2)) != NULL && res <= send) { - count += 1; - res += 1; - } - return count; -} - -static int str_count(bvm *vm) -{ - be_pushint(vm, str_operation(vm, _scount, 0)); - be_return(vm); -} - -static bbool _split_string(bvm *vm, int top) -{ - if (be_isstring(vm, 2)) { - const char *res; - int len1 = be_strlen(vm, 1); - int len2 = be_strlen(vm, 2); - const char *s1 = be_tostring(vm, 1); - const char *s2 = be_tostring(vm, 2); - bint count = len2 /* match when the pattern string is not empty */ - ? top >= 3 && be_isint(vm, 3) ? be_toint(vm, 3) : len1 - : 0; /* cannot match empty pattern string */ - while (count-- && (res = strstr(s1, s2)) != NULL) { - be_pushnstring(vm, s1, res - s1); - be_data_push(vm, -2); - be_pop(vm, 1); - s1 = res + len2; - } - be_pushstring(vm, s1); - be_data_push(vm, -2); - be_pop(vm, 1); - return btrue; - } - return bfalse; -} - -static bbool _split_index(bvm *vm) -{ - if (be_isint(vm, 2)) { - int len = be_strlen(vm, 1), idx = be_toindex(vm, 2); - const char *s = be_tostring(vm, 1); - idx = idx > len ? len : idx < -len ? -len : idx; - if (idx < 0) { - idx += len; - } - be_pushnstring(vm, s, idx); - be_data_push(vm, -2); - be_pop(vm, 1); - be_pushnstring(vm, s + idx, (size_t)len - idx); - be_data_push(vm, -2); - be_pop(vm, 1); - return btrue; - } - return bfalse; -} - -static int str_split(bvm *vm) -{ - int top = be_top(vm); - be_newobject(vm, "list"); - if (top >= 2 && be_isstring(vm, 1)) { - if (!_split_index(vm)) - _split_string(vm, top); - } - be_pop(vm, 1); - be_return(vm); -} - -static int str_i2hex(bvm *vm) -{ - int top = be_top(vm); - if (top && be_isint(vm, 1)) { - bint value = be_toint(vm, 1); - char fmt[10] = { "%" BE_INT_FMTLEN "X" }, buf[18]; - if (top >= 2 && be_isint(vm, 2)) { - bint num = be_toint(vm, 2); - if (num > 0 && num <= 16) { - snprintf(fmt, sizeof(fmt), "%%.%d" BE_INT_FMTLEN "X", (int)num); - } - } - snprintf(buf, sizeof(buf), fmt, value); - be_pushstring(vm, buf); - be_return(vm); - } - be_return_nil(vm); -} - -static int str_byte(bvm *vm) -{ - if (be_top(vm) && be_isstring(vm, 1)) { - const bbyte *s = (const bbyte *)be_tostring(vm, 1); - be_pushint(vm, *s); - be_return(vm); - } - be_return_nil(vm); -} - -static int str_char(bvm *vm) -{ - if (be_top(vm) && be_isint(vm, 1)) { - char c = be_toint(vm, 1) & 0xFF; - be_pushnstring(vm, &c, 1); - be_return(vm); - } - be_return_nil(vm); -} - -// boolean to select whether we call toupper() or tolower() -static int str_touplower(bvm *vm, bbool up) -{ - if (be_top(vm) && be_isstring(vm, 1)) { - const char *p, *s = be_tostring(vm, 1); - size_t len = (size_t)be_strlen(vm, 1); - char *buf, *q; - buf = q = be_pushbuffer(vm, len); - /* convert to lower case */ - for (p = s; *p != '\0'; ++p, ++q) { - *q = up ? toupper(*p) : tolower(*p); - } - be_pushnstring(vm, buf, len); /* make escape string from buffer */ - be_remove(vm, 2); /* remove buffer */ - be_return(vm); - } - be_return_nil(vm); -} - -static int str_tolower(bvm *vm) { - return str_touplower(vm, bfalse); -} - -static int str_toupper(bvm *vm) { - return str_touplower(vm, btrue); -} - -static int str_tr(bvm *vm) -{ - if (be_top(vm) == 3 && be_isstring(vm, 1) && be_isstring(vm, 2) && be_isstring(vm, 3)) { - const char *p, *s = be_tostring(vm, 1); - const char *t1 = be_tostring(vm, 2); - const char *t2 = be_tostring(vm, 3); - size_t len = (size_t)be_strlen(vm, 1); - char *buf, *q; - buf = be_pushbuffer(vm, len); - /* convert each char */ - for (p = s, q = buf; *p != '\0'; ++p, ++q) { - const char *p1, *p2; - *q = *p; /* default to no change */ - for (p1=t1, p2=t2; *p1 != '\0'; ++p1) { - if (*p == *p1) { - if (*p2) { - *q = *p2; - } else { - q--; /* remove this char */ - len--; - } - break; - } - if (*p2) { p2++; } - } - } - be_pushnstring(vm, buf, len); /* make escape string from buffer */ - be_remove(vm, 2); /* remove buffer */ - be_return(vm); - } - be_return_nil(vm); -} - -static int str_replace(bvm *vm) -{ - int top = be_top(vm); - if (top >= 3 && be_isstring(vm, 1) && be_isstring(vm, 2) && be_isstring(vm, 3)) { - be_pushntvfunction(vm, &str_split); - be_pushvalue(vm, 1); - be_pushvalue(vm, 2); - be_call(vm, 2); - be_pop(vm, 2); - - be_getmember(vm, -1, "concat"); /* get `concat` method of list */ - be_pushvalue(vm, -2); /* get list instance as first arg */ - be_pushvalue(vm, 3); - be_call(vm, 2); - be_pop(vm, 2); - be_return(vm); - } - be_return_nil(vm); -} - -static int str_escape(bvm *vm) -{ - int top = be_top(vm); - if (top >= 1 && be_isstring(vm, 1)) { - int quote = 'u'; - if (top >= 2 && be_isbool(vm, 2)) { - if (be_tobool(vm, 1)) { - quote = 'x'; - } - } - be_tostring(vm, 1); - be_toescape(vm, 1, quote); - be_pushvalue(vm, 1); - be_return(vm); - } - be_return_nil(vm); -} - -static int str_startswith(bvm *vm) -{ - int top = be_top(vm); - if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { - bbool case_insensitive = bfalse; - if (top >= 3 && be_isbool(vm, 3)) { - case_insensitive = be_tobool(vm, 3); - } - bbool result = bfalse; - const char *s = be_tostring(vm, 1); - const char *p = be_tostring(vm, 2); - size_t len = (size_t)be_strlen(vm, 2); - if (case_insensitive) { - if (str_strncasecmp(s, p, len) == 0) { - result = btrue; - } - } else { - if (strncmp(s, p, len) == 0) { - result = btrue; - } - } - be_pushbool(vm, result); - be_return(vm); - } - be_return_nil(vm); -} - -static int str_endswith(bvm *vm) -{ - int top = be_top(vm); - if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { - bbool case_insensitive = bfalse; - if (top >= 3 && be_isbool(vm, 3)) { - case_insensitive = be_tobool(vm, 3); - } - bbool result = bfalse; - const char *s = be_tostring(vm, 1); - const char *p = be_tostring(vm, 2); - size_t len = (size_t)be_strlen(vm, 2); - if (case_insensitive) { - if (str_strncasecmp(s + (int)strlen(s) - (int)len, p, len) == 0) { - result = btrue; - } - } else { - if (strncmp(s + (int)strlen(s) - (int)len, p, len) == 0) { - result = btrue; - } - } - be_pushbool(vm, result); - be_return(vm); - } - be_return_nil(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(string) { - be_native_module_function("format", be_str_format), - be_native_module_function("count", str_count), - be_native_module_function("split", str_split), - be_native_module_function("find", str_find), - be_native_module_function("hex", str_i2hex), - be_native_module_function("byte", str_byte), - be_native_module_function("char", str_char), - be_native_module_function("tolower", str_tolower), - be_native_module_function("toupper", str_toupper), - be_native_module_function("tr", str_tr), - be_native_module_function("escape", str_escape), - be_native_module_function("replace", str_replace), - be_native_module_function("startswith", str_startswith), - be_native_module_function("endswith", str_endswith), -}; - -be_define_native_module(string, NULL); -#else -/* @const_object_info_begin -module string (scope: global, depend: BE_USE_STRING_MODULE) { - format, func(be_str_format) - count, func(str_count) - split, func(str_split) - find, func(str_find) - hex, func(str_i2hex) - byte, func(str_byte) - char, func(str_char) - tolower, func(str_tolower) - toupper, func(str_toupper) - tr, func(str_tr) - escape, func(str_escape) - replace, func(str_replace) - startswith, func(str_startswith) - endswith, func(str_endswith) -} -@const_object_info_end */ -#include "../generate/be_fixed_string.h" -#endif - -#endif /* BE_USE_STRING_MODULE */ diff --git a/lib/libesp32/Berry/src/be_strlib.h b/lib/libesp32/Berry/src/be_strlib.h deleted file mode 100644 index 093c37c63877..000000000000 --- a/lib/libesp32/Berry/src/be_strlib.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_STRLIB_H -#define BE_STRLIB_H - -#include "be_object.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -bstring* be_strcat(bvm *vm, bstring *s1, bstring *s2); -int be_strcmp(bstring *s1, bstring *s2); -bstring* be_num2str(bvm *vm, bvalue *v); -void be_val2str(bvm *vm, int index); -int be_char2hex(int c); -size_t be_strlcpy(char *dst, const char *src, size_t size); -const char* be_splitpath(const char *path); -const char* be_splitname(const char *path); -const char* be_pushvfstr(bvm *vm, const char *format, va_list arg); -bstring* be_strindex(bvm *vm, bstring *str, bvalue *idx); -int be_str_format(bvm *vm); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32/Berry/src/be_sys.h b/lib/libesp32/Berry/src/be_sys.h deleted file mode 100644 index 79a8b3c692e9..000000000000 --- a/lib/libesp32/Berry/src/be_sys.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_SYS_H -#define BE_SYS_H - -#include - -/* directory information for directory traversal */ -typedef struct { - void *dir; - void *file; - const char *name; -} bdirinfo; - -#ifdef __cplusplus -extern "C" { -#endif - -void* be_fopen(const char *filename, const char *modes); -int be_fclose(void *hfile); -size_t be_fwrite(void *hfile, const void *buffer, size_t length); -size_t be_fread(void *hfile, void *buffer, size_t length); -char* be_fgets(void *hfile, void *buffer, int size); -int be_fseek(void *hfile, long offset); -long int be_ftell(void *hfile); -long int be_fflush(void *hfile); -size_t be_fsize(void *hfile); -int be_isdir(const char *path); -int be_isfile(const char *path); -int be_isexist(const char *path); -char* be_getcwd(char *buf, size_t size); -int be_chdir(const char *path); -int be_mkdir(const char *path); -int be_unlink(const char *filename); -int be_dirfirst(bdirinfo *info, const char *path); -int be_dirnext(bdirinfo *info); -int be_dirclose(bdirinfo *info); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32/Berry/src/be_syslib.c b/lib/libesp32/Berry/src/be_syslib.c deleted file mode 100644 index 650db845c445..000000000000 --- a/lib/libesp32/Berry/src/be_syslib.c +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_object.h" - -#if BE_USE_SYS_MODULE - -static int m_path(bvm *vm) -{ - be_getbuiltin(vm, "list"); - be_module_path(vm); - be_call(vm, 1); - be_pop(vm, 1); - be_return(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(sys){ - be_native_module_function("path", m_path) -}; - -be_define_native_module(sys, NULL); -#else -/* @const_object_info_begin -module sys (scope: global, depend: BE_USE_SYS_MODULE) { - path, func(m_path) -} -@const_object_info_end */ -#include "../generate/be_fixed_sys.h" -#endif - -#endif /* BE_USE_SYS_MODULE */ diff --git a/lib/libesp32/Berry/src/be_timelib.c b/lib/libesp32/Berry/src/be_timelib.c deleted file mode 100644 index a7938e4b7669..000000000000 --- a/lib/libesp32/Berry/src/be_timelib.c +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "berry.h" -#include - -#if BE_USE_TIME_MODULE - -static int m_time(bvm *vm) -{ - be_pushint(vm, (bint)time(NULL)); - be_return(vm); -} - -static void time_insert(bvm *vm, const char *key, int value) -{ - be_pushstring(vm, key); - be_pushint(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); -} - -static int m_dump(bvm *vm) -{ - if (be_top(vm) >= 1 && be_isint(vm, 1)) { - time_t ts = be_toint(vm, 1); - struct tm *t = localtime(&ts); - be_newobject(vm, "map"); - time_insert(vm, "year", t->tm_year + 1900); - time_insert(vm, "month", t->tm_mon + 1); - time_insert(vm, "day", t->tm_mday); - time_insert(vm, "hour", t->tm_hour); - time_insert(vm, "min", t->tm_min); - time_insert(vm, "sec", t->tm_sec); - time_insert(vm, "weekday", t->tm_wday); - time_insert(vm, "epoch", ts); - be_pop(vm, 1); - be_return(vm); - } - be_return_nil(vm); -} - -static int m_clock(bvm *vm) -{ - be_pushreal(vm, clock() / (breal)CLOCKS_PER_SEC); - be_return(vm); -} - -#if !BE_USE_PRECOMPILED_OBJECT -be_native_module_attr_table(time) { - be_native_module_function("time", m_time), - be_native_module_function("dump", m_dump), - be_native_module_function("clock", m_clock) -}; - -be_define_native_module(time, NULL); -#else -/* @const_object_info_begin -module time (scope: global, depend: BE_USE_TIME_MODULE) { - time, func(m_time) - dump, func(m_dump) - clock, func(m_clock) -} -@const_object_info_end */ -#include "../generate/be_fixed_time.h" -#endif - -#endif /* BE_USE_TIME_MODULE */ diff --git a/lib/libesp32/Berry/src/be_var.c b/lib/libesp32/Berry/src/be_var.c deleted file mode 100644 index 1a8e5b18c681..000000000000 --- a/lib/libesp32/Berry/src/be_var.c +++ /dev/null @@ -1,174 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_var.h" -#include "be_vm.h" -#include "be_vector.h" -#include "be_string.h" -#include "be_map.h" -#include "be_gc.h" -#include "be_class.h" -#include - -#define global(vm) ((vm)->gbldesc.global) -#define builtin(vm) ((vm)->gbldesc.builtin) - -extern BERRY_LOCAL bclass_array be_class_table; - -void be_globalvar_init(bvm *vm) -{ - global(vm).vtab = be_map_new(vm); - be_gc_fix(vm, gc_object(global(vm).vtab)); - be_vector_init(vm, &global(vm).vlist, sizeof(bvalue)); -#if !BE_USE_PRECOMPILED_OBJECT - builtin(vm).vtab = be_map_new(vm); - be_vector_init(vm, &builtin(vm).vlist, sizeof(bvalue)); - be_gc_fix(vm, gc_object(builtin(vm).vtab)); -#endif -} - -void be_globalvar_deinit(bvm *vm) -{ - global(vm).vtab = NULL; - be_vector_delete(vm, &global(vm).vlist); -#if !BE_USE_PRECOMPILED_OBJECT - builtin(vm).vtab = NULL; - be_vector_delete(vm, &builtin(vm).vlist); -#endif -} - -/* This function is called when the global was not found */ -/* If the name looked for matches a static class, a global with the class name is created lazily */ -/* Pre: no global exists with name `name`*/ -/* Returns: idx of newly created global, or -1 if not found */ -static int global_native_class_find(bvm *vm, bstring *name) -{ - const char* cl_name = str(name); - bclass_ptr* class_p = &be_class_table[0]; - for (; *class_p; class_p++) { - const bclass* cl = *class_p; - - if (!strcmp(str(cl->name), cl_name)) { - /* class name matches */ - int idx = be_global_new(vm, name); - bvalue *v = be_global_var(vm, idx); - var_setclass(v, (void*) cl); - return idx; - } - } - return -1; -} - -static int global_find(bvm *vm, bstring *name) -{ - bvalue *res = be_map_findstr(vm, global(vm).vtab, name); - if (res) { - return var_toidx(res) + be_builtin_count(vm); - } - return -1; /* not found */ -} - -int be_global_find(bvm *vm, bstring *name) -{ - int res = global_find(vm, name); - if (res < 0) { - res = be_builtin_find(vm, name); - } - if (res < 0) { - res = global_native_class_find(vm, name); - } - return res; -} - -static int global_new_anonymous(bvm *vm) -{ - int idx = be_global_count(vm); - /* allocate space for new variables */ - be_vector_resize(vm, &global(vm).vlist, idx + 1); - /* set the new variable to nil */ - var_setnil((bvalue *)global(vm).vlist.end); - return idx; -} - -int be_global_new(bvm *vm, bstring *name) -{ - int idx = global_find(vm, name); - if (idx == -1) { - bvalue *desc; - idx = global_new_anonymous(vm); - desc = be_map_insertstr(vm, global(vm).vtab, name, NULL); - var_setint(desc, idx); - idx += be_builtin_count(vm); - } - return idx; -} - -bvalue* be_global_var(bvm *vm, int index) -{ - int bcnt = be_builtin_count(vm); - if (index < bcnt) { - return be_vector_at(&builtin(vm).vlist, index); - } - index -= bcnt; - return be_vector_at(&global(vm).vlist, index); -} - -void be_global_release_space(bvm *vm) -{ - be_map_compact(vm, global(vm).vtab); - be_vector_release(vm, &global(vm).vlist); -} - -int be_builtin_find(bvm *vm, bstring *name) -{ - bvalue *res = be_map_findstr(vm, builtin(vm).vtab, name); - if (res) { - return var_toidx(res); - } - return -1; /* not found */ -} - -bstring* be_builtin_name(bvm *vm, int index) -{ - bmap *map = builtin(vm).vtab; - bmapnode *end, *node = map->slots; - for (end = node + map->size; node < end; ++node) { - if (var_isstr(&node->key) && node->value.v.i == index) { - return node->key.v.s; - } - } - return NULL; -} - -#if !BE_USE_PRECOMPILED_OBJECT -int be_builtin_new(bvm *vm, bstring *name) -{ - int idx = be_builtin_find(vm, name); - if (idx == -1) { - bvalue *desc; - idx = be_map_count(builtin(vm).vtab); - desc = be_map_insertstr(vm, builtin(vm).vtab, name, NULL); - var_setint(desc, idx); - be_vector_resize(vm, &builtin(vm).vlist, idx + 1); - /* set the new variable to nil */ - var_setnil((bvalue*)(builtin(vm).vlist.end)); - } - return idx; -} - -void be_bulitin_release_space(bvm *vm) -{ - be_map_compact(vm, builtin(vm).vtab); - be_vector_release(vm, &builtin(vm).vlist); -} -#else -void be_const_builtin_set(bvm *vm, const bmap *map, const bvector *vec) -{ - builtin(vm).vtab = cast(bmap*, map); - builtin(vm).vlist = *vec; -} -#endif diff --git a/lib/libesp32/Berry/src/be_var.h b/lib/libesp32/Berry/src/be_var.h deleted file mode 100644 index 6b9908a6b7b1..000000000000 --- a/lib/libesp32/Berry/src/be_var.h +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_VAR_H -#define BE_VAR_H - -#include "be_object.h" - -#define be_global_count(vm) \ - be_vector_count(&(vm)->gbldesc.global.vlist) - -#define be_builtin_count(vm) \ - be_vector_count(&(vm)->gbldesc.builtin.vlist) - -void be_globalvar_init(bvm *vm); -void be_globalvar_deinit(bvm *vm); -int be_global_find(bvm *vm, bstring *name); -int be_global_new(bvm *vm, bstring *name); -bvalue* be_global_var(bvm *vm, int index); -void be_global_release_space(bvm *vm); -int be_builtin_find(bvm *vm, bstring *name); -bstring* be_builtin_name(bvm *vm, int index); -int be_builtin_new(bvm *vm, bstring *name); -void be_bulitin_release_space(bvm *vm); -void be_const_builtin_set(bvm *vm, const bmap *map, const bvector *vec); - -#endif diff --git a/lib/libesp32/Berry/src/be_vector.c b/lib/libesp32/Berry/src/be_vector.c deleted file mode 100644 index 65ac83350aed..000000000000 --- a/lib/libesp32/Berry/src/be_vector.c +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_vector.h" -#include "be_mem.h" -#include - -/* initialize a vector, the vector structure itself is usually allocated - * on the stack, and the data is allocated from the heap. - **/ -void be_vector_init(bvm *vm, bvector *vector, int size) -{ - vector->capacity = 2; /* the default capacity */ - vector->size = size; - vector->count = 0; - vector->data = be_malloc(vm, (size_t)vector->capacity * size); - vector->end = (char*)vector->data - size; - memset(vector->data, 0, (size_t)vector->capacity * size); -} - -void be_vector_delete(bvm *vm, bvector *vector) -{ - be_free(vm, vector->data, (size_t)vector->capacity * vector->size); -} - -void* be_vector_at(bvector *vector, int index) -{ - return (char*)vector->data + (size_t)index * vector->size; -} - -void be_vector_push(bvm *vm, bvector *vector, void *data) -{ - size_t size = vector->size; - size_t capacity = vector->capacity; - size_t count = vector->count++; - if (count >= capacity) { - int newcap = be_nextsize(vector->capacity); - vector->data = be_realloc(vm, - vector->data, vector->capacity * size, newcap * size); - vector->end = (char*)vector->data + count * size; - vector->capacity = newcap; - } else { - vector->end = (char*)vector->end + size; - } - if (data != NULL) { - memcpy(vector->end, data, size); - } -} - -/* clear the expanded portion if the memory expands */ -void be_vector_push_c(bvm *vm, bvector *vector, void *data) -{ - int capacity = vector->capacity + 1; - be_vector_push(vm, vector, data); - if (vector->capacity > capacity) { - size_t size = ((size_t)vector->capacity - capacity) * vector->size; - memset(be_vector_at(vector, capacity), 0, size); - } -} - -void be_vector_remove_end(bvector *vector) -{ - be_assert(vector->count > 0); - vector->count--; - vector->end = (char*)vector->end - vector->size; -} - -void be_vector_resize(bvm *vm, bvector *vector, int count) -{ - size_t size = vector->size; - be_assert(count >= 0); - if (count != be_vector_count(vector)) { - int newcap = be_nextsize(count); - if (newcap > vector->capacity) { /* extended capacity */ - vector->data = be_realloc(vm, - vector->data, vector->capacity * size, newcap * size); - vector->capacity = newcap; - } - vector->count = count; - if (count == 0) { - vector->end = (char*)vector->data - size; - } else { - vector->end = (char*)vector->data + size * ((size_t)count - 1); - } - } -} - -void be_vector_clear(bvector *vector) -{ - vector->count = 0; - vector->end = (char*)vector->data - vector->size; -} - -/* free not used */ -void* be_vector_release(bvm *vm, bvector *vector) -{ - size_t size = vector->size; - int count = be_vector_count(vector); - if (count == 0) { - be_free(vm, vector->data, vector->capacity * size); - vector->capacity = 0; - vector->data = NULL; - vector->end = NULL; - } else if (count < vector->capacity) { - vector->data = be_realloc(vm, - vector->data, vector->capacity * size, count * size); - vector->end = (char*)vector->data + ((size_t)count - 1) * size; - vector->capacity = count; - } - return vector->data; -} - -/* use binary search to find the vector capacity between 0-1024 */ -static int binary_search(int value) -{ - static const uint16_t tab[] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, - 20, 24, 28, 32, 40, 48, 64, 96, 128, - 192, 256, 384, 512, 768, 1024 - }; - const uint16_t *low = tab; - const uint16_t *high = tab + array_count(tab) - 1; - while (low <= high) { - const uint16_t *mid = low + ((high - low) >> 1); - if (*mid == value) { - return mid[1]; - } - if (*mid < value) { - low = mid + 1; - } else { - high = mid - 1; - } - } - return *low; -} - -static int nextpow(int value) -{ - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - return value + 1; -} - -int be_nextsize(int size) -{ - if (size < 1024) { - return binary_search(size); - } - return nextpow(size); -} diff --git a/lib/libesp32/Berry/src/be_vector.h b/lib/libesp32/Berry/src/be_vector.h deleted file mode 100644 index 15f399cc6378..000000000000 --- a/lib/libesp32/Berry/src/be_vector.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_VECTOR_H -#define BE_VECTOR_H - -#include "be_object.h" - -/* =============================== defines =============================== */ -#define be_vector_data(vector) ((vector)->data) -#define be_vector_first(vector) ((vector)->data) -#define be_vector_isend(vector, item) ((item) > (vector)->end) -#define be_vector_isempty(vector) (!(vector)->count) -#define be_vector_end(vector) ((vector)->end) -#define be_vector_count(vector) ((vector)->count) -#define be_vector_capacity(vector) ((vector)->capacity) -#define be_stack_init(vm, stack, size) be_vector_init(vm, stack, size) -#define be_stack_delete(vm, stack) be_vector_delete(vm, stack) -#define be_stack_clear(stack) be_vector_clear(stack) -#define be_stack_push(vm, stack, data) be_vector_push(vm, stack, data) -#define be_stack_pop(stack) be_vector_remove_end(stack) -#define be_stack_top(stack) be_vector_end(stack) -#define be_stack_base(stack) be_vector_first(stack) -#define be_stack_count(stack) be_vector_count(stack) -#define be_stack_isempty(stack) be_vector_isempty(stack) - -/* ========================== function extern ========================== */ -void be_vector_init(bvm *vm, bvector *vector, int size); -void be_vector_delete(bvm *vm, bvector *vector); -void* be_vector_at(bvector *vector, int index); -void be_vector_push(bvm *vm, bvector *vector, void *data); -void be_vector_push_c(bvm *vm, bvector *vector, void *data); -void be_vector_remove_end(bvector *vector); -void be_vector_resize(bvm *vm, bvector *vector, int count); -void be_vector_clear(bvector *vector); -void* be_vector_release(bvm *vm, bvector *vector); -int be_nextsize(int value); - -#endif diff --git a/lib/libesp32/Berry/src/be_vm.c b/lib/libesp32/Berry/src/be_vm.c deleted file mode 100644 index 78fcc486b321..000000000000 --- a/lib/libesp32/Berry/src/be_vm.c +++ /dev/null @@ -1,1419 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#include "be_vm.h" -#include "be_decoder.h" -#include "be_string.h" -#include "be_strlib.h" -#include "be_class.h" -#include "be_func.h" -#include "be_vector.h" -#include "be_list.h" -#include "be_map.h" -#include "be_module.h" -#include "be_mem.h" -#include "be_var.h" -#include "be_gc.h" -#include "be_exec.h" -#include "be_debug.h" -#include "be_libs.h" -#include -#include - -#define NOT_METHOD BE_NONE - -#define vm_error(vm, except, ...) \ - be_raise(vm, except, be_pushfstring(vm, __VA_ARGS__)) - -#define RA() (reg + IGET_RA(ins)) /* Get value of register A */ -#define RKB() ((isKB(ins) ? ktab : reg) + KR2idx(IGET_RKB(ins))) /* Get value of register or constant B */ -#define RKC() ((isKC(ins) ? ktab : reg) + KR2idx(IGET_RKC(ins))) /* Get value of register or constant C */ - -#define var2cl(_v) cast(bclosure*, var_toobj(_v)) /* cast var to closure */ -#define var2real(_v) (var_isreal(_v) ? (_v)->v.r : (breal)(_v)->v.i) /* get var as real or convert to real if integer */ -#define val2bool(v) ((v) ? btrue : bfalse) /* get var as bool (trur if non zero) */ -#define ibinop(op, a, b) ((a)->v.i op (b)->v.i) /* apply binary operator to both arguments as integers */ - -#if BE_USE_DEBUG_HOOK - #define DEBUG_HOOK() \ - if (vm->hookmask & BE_HOOK_LINE) { \ - do_linehook(vm); \ - reg = vm->reg; \ - } -#else - #define DEBUG_HOOK() -#endif - -#if BE_USE_PERF_COUNTERS - #define COUNTER_HOOK() \ - vm->counter_ins++; -#else - #define COUNTER_HOOK() -#endif - -#if BE_USE_PERF_COUNTERS - #define VM_HEARTBEAT() \ - if ((vm->counter_ins & ((1<<(BE_VM_OBSERVABILITY_SAMPLING - 1))-1) ) == 0) { /* call every 2^BE_VM_OBSERVABILITY_SAMPLING instructions */ \ - if (vm->obshook != NULL) \ - (*vm->obshook)(vm, BE_OBS_VM_HEARTBEAT, vm->counter_ins); \ - } -#else - #define VM_HEARTBEAT() -#endif - -#define vm_exec_loop() \ - loop: \ - DEBUG_HOOK(); \ - COUNTER_HOOK(); \ - VM_HEARTBEAT(); \ - switch (IGET_OP(ins = *vm->ip++)) - -#if BE_USE_SINGLE_FLOAT - #define mathfunc(func) func##f -#else - #define mathfunc(func) func -#endif - -#define opcase(opcode) case OP_##opcode -#define dispatch() goto loop - -#define equal_rule(op, iseq) \ - bbool res; \ - be_assert(!var_isstatic(a)); \ - be_assert(!var_isstatic(b)); \ - if (var_isint(a) && var_isint(b)) { \ - res = ibinop(op, a, b); \ - } else if (var_isnumber(a) && var_isnumber(b)) { \ - res = var2real(a) op var2real(b); \ - } else if (var_isinstance(a) && !var_isnil(b)) { \ - res = object_eqop(vm, #op, iseq, a, b); \ - } else if (var_primetype(a) == var_primetype(b)) { /* same types */ \ - if (var_isnil(a)) { /* nil op nil */ \ - res = 1 op 1; \ - } else if (var_isbool(a)) { /* bool op bool */ \ - res = var_tobool(a) op var_tobool(b); \ - } else if (var_isstr(a)) { /* string op string */ \ - res = 1 op be_eqstr(a->v.s, b->v.s); \ - } else if (var_isclass(a) || var_isfunction(a) || var_iscomptr(a)) { \ - res = var_toobj(a) op var_toobj(b); \ - } else { \ - binop_error(vm, #op, a, b); \ - res = bfalse; /* will not be executed */ \ - } \ - } else { /* different types */ \ - res = 1 op 0; \ - } \ - return res - -/* when running on ESP32 in IRAM, there is a bug in early chip revision */ -#ifdef ESP32 - #define relop_rule(op) \ - bbool res; \ - if (var_isint(a) && var_isint(b)) { \ - res = ibinop(op, a, b); \ - } else if (var_isnumber(a) && var_isnumber(b)) { \ - /* res = var2real(a) op var2real(b); */ \ - union bvaldata x, y; /* TASMOTA workaround for ESP32 rev0 bug */ \ - x.i = a->v.i;\ - if (var_isint(a)) { x.r = (breal) x.i; }\ - y.i = b->v.i;\ - if (var_isint(b)) { y.r = (breal) y.i; }\ - res = x.r op y.r; \ - } else if (var_isstr(a) && var_isstr(b)) { \ - bstring *s1 = var_tostr(a), *s2 = var_tostr(b); \ - res = be_strcmp(s1, s2) op 0; \ - } else if (var_isinstance(a)) { \ - binstance *obj = var_toobj(a); \ - object_binop(vm, #op, *a, *b); \ - check_bool(vm, obj, #op); \ - res = var_tobool(vm->top); \ - } else { \ - binop_error(vm, #op, a, b); \ - res = bfalse; /* will not be executed */ \ - } \ - return res -#else // ESP32 - #define relop_rule(op) \ - bbool res; \ - if (var_isint(a) && var_isint(b)) { \ - res = ibinop(op, a, b); \ - } else if (var_isnumber(a) && var_isnumber(b)) { \ - res = var2real(a) op var2real(b); \ - } else if (var_isstr(a) && var_isstr(b)) { \ - bstring *s1 = var_tostr(a), *s2 = var_tostr(b); \ - res = be_strcmp(s1, s2) op 0; \ - } else if (var_isinstance(a)) { \ - binstance *obj = var_toobj(a); \ - object_binop(vm, #op, *a, *b); \ - check_bool(vm, obj, #op); \ - res = var_tobool(vm->top); \ - } else { \ - binop_error(vm, #op, a, b); \ - res = bfalse; /* will not be executed */ \ - } \ - return res -#endif // ESP32 - -#define bitwise_block(op) \ - bvalue *dst = RA(), *a = RKB(), *b = RKC(); \ - if (var_isint(a) && var_isint(b)) { \ - var_setint(dst, ibinop(op, a, b)); \ - } else if (var_isinstance(a)) { \ - ins_binop(vm, #op, ins); \ - } else { \ - binop_error(vm, #op, a, b); \ - } - -#define push_native(_vm, _f, _ns, _t) { \ - precall(_vm, _f, _ns, _t); \ - _vm->cf->status = PRIM_FUNC; \ -} - -static void prep_closure(bvm *vm, int pos, int argc, int mode); - -static void attribute_error(bvm *vm, const char *t, bvalue *b, bvalue *c) -{ - const char *attr = var_isstr(c) ? str(var_tostr(c)) : be_vtype2str(c); - vm_error(vm, "attribute_error", - "'%s' value has no %s '%s'", be_vtype2str(b), t, attr); -} - -static void binop_error(bvm *vm, const char *op, bvalue *a, bvalue *b) -{ - vm_error(vm, "type_error", - "unsupported operand type(s) for %s: '%s' and '%s'", - op, be_vtype2str(a), be_vtype2str(b)); -} - -static void unop_error(bvm *vm, const char *op, bvalue *a) -{ - vm_error(vm, "type_error", - "unsupported operand type(s) for %s: '%s'", - op, be_vtype2str(a)); -} - -static void call_error(bvm *vm, bvalue *v) -{ - vm_error(vm, "type_error", - "'%s' value is not callable", be_vtype2str(v)); -} - -/* Check that the return value is bool or raise an exception */ -/* `obj` and `method` are only passed for error reporting */ -static void check_bool(bvm *vm, binstance *obj, const char *method) -{ - if (!var_isbool(vm->top)) { - const char *name = str(be_instance_name(obj)); - vm_error(vm, "type_error", - "`%s::%s` return value error, the expected type is 'bool'", - strlen(name) ? name : "", method); - } -} - -#if BE_USE_DEBUG_HOOK -static void do_linehook(bvm *vm) -{ - bcallframe *cf = vm->cf; - bclosure *cl = var_toobj(cf->func); - int pc = cast_int(vm->ip - cl->proto->code); - if (!pc || pc > cf->lineinfo->endpc) { - while (pc > cf->lineinfo->endpc) - cf->lineinfo++; - be_callhook(vm, BE_HOOK_LINE); - } else { - blineinfo *linfo = cf->lineinfo; - blineinfo *base = cl->proto->lineinfo; - while (linfo > base && pc <= linfo[-1].endpc) - linfo--; - if (cf->lineinfo != linfo) { - cf->lineinfo = linfo; - be_callhook(vm, BE_HOOK_LINE); - } - } -} -#endif - -/* Prepare the stack for the function/method call */ -/* `func` is a pointer to the function/method on the stack, it contains the closure before call and the result after the call */ -/* `nstackˋ is the stack depth used by the function (determined by compiler), we add BE_STACK_FREE_MIN as a safety margin */ -static void precall(bvm *vm, bvalue *func, int nstack, int mode) -{ - bcallframe *cf; - int expan = nstack + BE_STACK_FREE_MIN; /* `expan` is the minimum required space on the stack */ - if (vm->stacktop < func + expan) { /* do we have too little space left on the stack? */ - size_t fpos = func - vm->stack; /* compute offset of `func` from base stack, in case stack is reallocated and base address changes */ - be_stack_expansion(vm, expan); /* expand stack (vector object), warning stack address changes */ - func = vm->stack + fpos; /* recompute `func` address with new stack address */ - } - be_stack_push(vm, &vm->callstack, NULL); /* push a NULL value on callstack */ - cf = be_stack_top(&vm->callstack); /* get address of new callframe at top of callstack */ - cf->func = func - mode; - cf->top = vm->top; /* save previous stack top */ - cf->reg = vm->reg; /* save previous stack base */ - vm->reg = func + 1; /* new stack base is right after function */ - vm->top = vm->reg + nstack; /* new stack top is above the registers used by the function, so we don´t mess with them */ - vm->cf = cf; /* set new current callframe */ -} - -/* Prepare call of closure, setting the instruction pointer (ip) */ -static void push_closure(bvm *vm, bvalue *func, int nstack, int mode) -{ - bclosure *cl = var_toobj(func); - precall(vm, func, nstack, mode); - vm->cf->ip = vm->ip; - vm->cf->status = NONE_FLAG; - vm->ip = cl->proto->code; -#if BE_USE_DEBUG_HOOK - vm->cf->lineinfo = cl->proto->lineinfo; - be_callhook(vm, BE_HOOK_CALL); -#endif -} - -static void ret_native(bvm *vm) -{ - bcallframe *_cf = vm->cf; - vm->reg = _cf->reg; - vm->top = _cf->top; - be_stack_pop(&vm->callstack); - vm->cf = be_stack_top(&vm->callstack); -} - -static bbool obj2bool(bvm *vm, bvalue *var) -{ - binstance *obj = var_toobj(var); - bstring *tobool = str_literal(vm, "tobool"); - /* get operator method */ - int type = be_instance_member(vm, obj, tobool, vm->top); - if (type != BE_NONE && type != BE_NIL) { - vm->top[1] = *var; /* move self to argv[0] */ - be_dofunc(vm, vm->top, 1); /* call method 'tobool' */ - /* check the return value */ - check_bool(vm, obj, "tobool"); - return var_tobool(vm->top); - } - return btrue; -} - -bbool be_value2bool(bvm *vm, bvalue *v) -{ - switch (var_basetype(v)) { - case BE_NIL: - return bfalse; - case BE_BOOL: - return var_tobool(v); - case BE_INT: - return val2bool(v->v.i); - case BE_REAL: - return val2bool(v->v.r); - case BE_STRING: - return str_len(var_tostr(v)) != 0; - case BE_COMPTR: - return var_toobj(v) != NULL; - case BE_COMOBJ: - return ((bcommomobj*)var_toobj(v))->data != NULL; - case BE_INSTANCE: - return obj2bool(vm, v); - default: - return btrue; - } -} - -static void obj_method(bvm *vm, bvalue *o, bstring *attr, bvalue *dst) -{ - binstance *obj = var_toobj(o); - int type = be_instance_member_simple(vm, obj, attr, dst); - if (basetype(type) != BE_FUNCTION) { - vm_error(vm, "attribute_error", - "the '%s' object has no method '%s'", - str(be_instance_name(obj)), str(attr)); - } -} - -static int obj_attribute(bvm *vm, bvalue *o, bstring *attr, bvalue *dst) -{ - binstance *obj = var_toobj(o); - int type = be_instance_member(vm, obj, attr, dst); - if (type == BE_NONE) { - vm_error(vm, "attribute_error", - "the '%s' object has no attribute '%s'", - str(be_instance_name(obj)), str(attr)); - } - return type; -} - -static int class_attribute(bvm *vm, bvalue *o, bvalue *c, bvalue *dst) -{ - bstring *attr = var_tostr(c); - bclass *obj = var_toobj(o); - int type = be_class_member(vm, obj, attr, dst); - if (type == BE_NONE || type == BE_INDEX) { - vm_error(vm, "attribute_error", - "the '%s' class has no static attribute '%s'", - str(obj->name), str(attr)); - } - return type; -} - -static int module_attribute(bvm *vm, bvalue *o, bvalue *c, bvalue *dst) -{ - bstring *attr = var_tostr(c); - bmodule *module = var_toobj(o); - int type = be_module_attr(vm, module, attr, dst); - if (type == BE_NONE) { - vm_error(vm, "attribute_error", - "module '%s' has no member '%s'", - be_module_name(module), str(attr)); - } - return type; -} - -static bbool object_eqop(bvm *vm, - const char *op, bbool iseq, bvalue *a, bvalue *b) -{ - binstance *o = var_toobj(a); - bvalue self = *a, other = *b; - bbool isself = var_isinstance(b) && o == var_toobj(b); - /* first, try to call the overloaded operator of the object */ - int type = be_instance_member(vm, o, be_newstr(vm, op), vm->top); - if (basetype(type) == BE_FUNCTION) { /* call method */ - bvalue *top = vm->top; - top[1] = self; /* move self to argv[0] */ - top[2] = other; /* move other to argv[1] */ - be_incrtop(vm); /* prevent collection results */ - be_dofunc(vm, top, 2); /* call method 'item' */ - be_stackpop(vm, 1); - check_bool(vm, o, op); /* check return value */ - return var_tobool(vm->top); /* copy result to dst */ - } - /* the default equal operation rule */ - return iseq == isself; /* check object self */ -} - -static void object_binop(bvm *vm, const char *op, bvalue self, bvalue other) -{ - bvalue *top = vm->top; - /* get operator method (possible GC) */ - obj_method(vm, &self, be_newstr(vm, op), vm->top); - top[1] = self; /* move self to argv[0] */ - top[2] = other; /* move other to argv[1] */ - be_incrtop(vm); /* prevent collection results */ - be_dofunc(vm, top, 2); /* call method 'item' */ - be_stackpop(vm, 1); -} - -#define ins_binop(vm, op, ins) { \ - object_binop(vm, op, *RKB(), *RKC()); \ - reg = vm->reg; \ - *RA() = *vm->top; /* copy result to dst */ \ -} - -static void ins_unop(bvm *vm, const char *op, bvalue self) -{ - bvalue *top = vm->top; - /* get operator method (possible GC) */ - obj_method(vm, &self, be_newstr(vm, op), vm->top); - top[1] = self; /* move self to argv[0] */ - be_dofunc(vm, top, 1); /* call method 'item' */ -} - -bbool be_vm_iseq(bvm *vm, bvalue *a, bvalue *b) -{ - equal_rule(==, btrue); -} - -bbool be_vm_isneq(bvm *vm, bvalue *a, bvalue *b) -{ - equal_rule(!=, bfalse); -} - -bbool be_vm_islt(bvm *vm, bvalue *a, bvalue *b) -{ - relop_rule(<); -} - -bbool be_vm_isle(bvm *vm, bvalue *a, bvalue *b) -{ - relop_rule(<=); -} - -bbool be_vm_isgt(bvm *vm, bvalue *a, bvalue *b) -{ - relop_rule(>); -} - -bbool be_vm_isge(bvm *vm, bvalue *a, bvalue *b) -{ - relop_rule(>=); -} - -static void make_range(bvm *vm, bvalue lower, bvalue upper) -{ - /* get method 'item' (possible GC) */ - int idx = be_builtin_find(vm, str_literal(vm, "range")); - bvalue *top = vm->top; - top[0] = *be_global_var(vm, idx); - top[1] = lower; /* move lower to argv[0] */ - top[2] = upper; /* move upper to argv[1] */ - vm->top += 3; /* prevent collection results */ - be_dofunc(vm, top, 2); /* call method 'item' */ - vm->top -= 3; -} - -static void connect_str(bvm *vm, bstring *a, bvalue *b) -{ - bstring *s; - if (var_isstr(b)) { - s = be_strcat(vm, a, var_tostr(b)); - var_setstr(vm->top, s); - } else { - *vm->top++ = *b; - be_val2str(vm, -1); - b = vm->top - 1; - s = be_strcat(vm, a, var_tostr(b)); - var_setstr(b, s); - vm->top -= 1; - } -} - -BERRY_API bvm* be_vm_new(void) -{ - bvm *vm = be_os_malloc(sizeof(bvm)); - be_assert(vm != NULL); - memset(vm, 0, sizeof(bvm)); /* clear all members */ - be_gc_init(vm); - be_string_init(vm); - be_stack_init(vm, &vm->callstack, sizeof(bcallframe)); - be_stack_init(vm, &vm->refstack, sizeof(binstance*)); - be_stack_init(vm, &vm->exceptstack, sizeof(struct bexecptframe)); - be_stack_init(vm, &vm->tracestack, sizeof(bcallsnapshot)); - vm->stack = be_malloc(vm, sizeof(bvalue) * BE_STACK_START); - vm->stacktop = vm->stack + BE_STACK_START; - vm->reg = vm->stack; - vm->top = vm->reg; - be_globalvar_init(vm); - be_gc_setpause(vm, 1); - be_loadlibs(vm); - vm->compopt = 0; - vm->bytesmaxsize = BE_BYTES_MAX_SIZE; - vm->obshook = NULL; - vm->ctypefunc = NULL; -#if BE_USE_PERF_COUNTERS - vm->counter_ins = 0; - vm->counter_enter = 0; - vm->counter_call = 0; - vm->counter_get = 0; - vm->counter_set = 0; - vm->counter_get_global = 0; - vm->counter_try = 0; - vm->counter_exc = 0; - vm->counter_gc_kept = 0; - vm->counter_gc_freed = 0; - vm->counter_mem_alloc = 0; - vm->counter_mem_free = 0; - vm->counter_mem_realloc = 0; -#endif - return vm; -} - -BERRY_API void be_vm_delete(bvm *vm) -{ - be_gc_deleteall(vm); - be_string_deleteall(vm); - be_stack_delete(vm, &vm->callstack); - be_stack_delete(vm, &vm->refstack); - be_stack_delete(vm, &vm->exceptstack); - be_stack_delete(vm, &vm->tracestack); - be_free(vm, vm->stack, (vm->stacktop - vm->stack) * sizeof(bvalue)); - be_globalvar_deinit(vm); - be_gc_free_memory_pools(vm); -#if BE_USE_DEBUG_HOOK - /* free native hook */ - if (var_istype(&vm->hook, BE_COMPTR)) - be_free(vm, var_toobj(&vm->hook), sizeof(struct bhookblock)); -#endif - /* free VM structure */ - be_os_free(vm); -} - -static void vm_exec(bvm *vm) -{ - bclosure *clos; - bvalue *ktab, *reg; - binstruction ins; - vm->cf->status |= BASE_FRAME; -newframe: /* a new call frame */ - be_assert(var_isclosure(vm->cf->func)); - clos = var_toobj(vm->cf->func); /* `clos` is the current function/closure */ - ktab = clos->proto->ktab; /* `ktab` is the current constant table */ - reg = vm->reg; /* `reg` is the current stack base for the callframe */ -#if BE_USE_PERF_COUNTERS - vm->counter_enter++; -#endif - vm_exec_loop() { - opcase(LDNIL): { - var_setnil(RA()); - dispatch(); - } - opcase(LDBOOL): { - bvalue *v = RA(); - var_setbool(v, IGET_RKB(ins)); - if (IGET_RKC(ins)) { /* skip next instruction */ - vm->ip += 1; - } - dispatch(); - } - opcase(LDINT): { - bvalue *v = RA(); - var_setint(v, IGET_sBx(ins)); - dispatch(); - } - opcase(LDCONST): { - bvalue *dst = RA(); - *dst = ktab[IGET_Bx(ins)]; - dispatch(); - } - opcase(GETGBL): { - bvalue *v = RA(); - int idx = IGET_Bx(ins); - *v = *be_global_var(vm, idx); - dispatch(); - } - opcase(GETNGBL): { /* get Global by name */ -#if BE_USE_PERF_COUNTERS - vm->counter_get_global++; -#endif - bvalue *v = RA(); - bvalue *b = RKB(); - if (var_isstr(b)) { - bstring *name = var_tostr(b); - int idx = be_global_find(vm, name); - if (idx > -1) { - *v = *be_global_var(vm, idx); - } else { - vm_error(vm, "attribute_error", "'%s' undeclared", str(name)); - } - } else { - vm_error(vm, "internal_error", "global name must be a string"); - } - dispatch(); - } - opcase(SETNGBL): { /* set Global by name */ - bvalue *v = RA(); - bvalue *b = RKB(); - if (var_isstr(b)) { - bstring *name = var_tostr(b); - int idx = be_global_new(vm, name); - *be_global_var(vm, idx) = *v; - } else { - vm_error(vm, "internal_error", "global name must be a string"); - } - dispatch(); - } - opcase(SETGBL): { - bvalue *v = RA(); - int idx = IGET_Bx(ins); - *be_global_var(vm, idx) = *v; - dispatch(); - } - opcase(GETUPV): { - bvalue *v = RA(); - int idx = IGET_Bx(ins); - be_assert(*clos->upvals != NULL); - *v = *clos->upvals[idx]->value; - dispatch(); - } - opcase(SETUPV): { - bvalue *v = RA(); - int idx = IGET_Bx(ins); - be_assert(*clos->upvals != NULL); - *clos->upvals[idx]->value = *v; - dispatch(); - } - opcase(MOVE): { - bvalue *dst = RA(); - *dst = *RKB(); - dispatch(); - } - opcase(ADD): { - bvalue *dst = RA(), *a = RKB(), *b = RKC(); - if (var_isint(a) && var_isint(b)) { - var_setint(dst, ibinop(+, a, b)); - } else if (var_isnumber(a) && var_isnumber(b)) { -#ifdef ESP32 /* when running on ESP32 in IRAM, there is a bug in early chip revision */ - union bvaldata x, y; // TASMOTA workaround for ESP32 rev0 bug - x.i = a->v.i; - if (var_isint(a)) { x.r = (breal) x.i; } - y.i = b->v.i; - if (var_isint(b)) { y.r = (breal) y.i; } - var_setreal(dst, x.r + y.r); -#else // ESP32 - breal x = var2real(a), y = var2real(b); - var_setreal(dst, x + y); -#endif // ESP32 - } else if (var_isstr(a) && var_isstr(b)) { /* strcat */ - bstring *s = be_strcat(vm, var_tostr(a), var_tostr(b)); - reg = vm->reg; - dst = RA(); - var_setstr(dst, s); - } else if (var_isinstance(a)) { - ins_binop(vm, "+", ins); - } else { - binop_error(vm, "+", a, b); - } - dispatch(); - } - opcase(SUB): { - bvalue *dst = RA(), *a = RKB(), *b = RKC(); - if (var_isint(a) && var_isint(b)) { - var_setint(dst, ibinop(-, a, b)); - } else if (var_isnumber(a) && var_isnumber(b)) { -#if CONFIG_IDF_TARGET_ESP32 /* when running on ESP32 in IRAM, there is a bug in early chip revision */ - union bvaldata x, y; // TASMOTA workaround for ESP32 rev0 bug - x.i = a->v.i; - if (var_isint(a)) { x.r = (breal) x.i; } - y.i = b->v.i; - if (var_isint(b)) { y.r = (breal) y.i; } - var_setreal(dst, x.r - y.r); -#else // CONFIG_IDF_TARGET_ESP32 - breal x = var2real(a), y = var2real(b); - var_setreal(dst, x - y); -#endif // CONFIG_IDF_TARGET_ESP32 - } else if (var_isinstance(a)) { - ins_binop(vm, "-", ins); - } else { - binop_error(vm, "-", a, b); - } - dispatch(); - } - opcase(MUL): { - bvalue *dst = RA(), *a = RKB(), *b = RKC(); - if (var_isint(a) && var_isint(b)) { - var_setint(dst, ibinop(*, a, b)); - } else if (var_isnumber(a) && var_isnumber(b)) { -#if CONFIG_IDF_TARGET_ESP32 /* when running on ESP32 in IRAM, there is a bug in early chip revision */ - union bvaldata x, y; // TASMOTA workaround for ESP32 rev0 bug - x.i = a->v.i; - if (var_isint(a)) { x.r = (breal) x.i; } - y.i = b->v.i; - if (var_isint(b)) { y.r = (breal) y.i; } - var_setreal(dst, x.r * y.r); -#else // CONFIG_IDF_TARGET_ESP32 - breal x = var2real(a), y = var2real(b); - var_setreal(dst, x * y); -#endif // CONFIG_IDF_TARGET_ESP32 - } else if (var_isinstance(a)) { - ins_binop(vm, "*", ins); - } else { - binop_error(vm, "*", a, b); - } - dispatch(); - } - opcase(DIV): { - bvalue *dst = RA(), *a = RKB(), *b = RKC(); - if (var_isint(a) && var_isint(b)) { - bint x = var_toint(a), y = var_toint(b); - if (y == 0) { - vm_error(vm, "divzero_error", "division by zero"); - } else { - var_setint(dst, x / y); - } - } else if (var_isnumber(a) && var_isnumber(b)) { -#if CONFIG_IDF_TARGET_ESP32 /* when running on ESP32 in IRAM, there is a bug in early chip revision */ - union bvaldata x0, y0; // TASMOTA workaround for ESP32 rev0 bug - x0.i = a->v.i; - if (var_isint(a)) { x0.r = (breal) x0.i; } - y0.i = b->v.i; - if (var_isint(b)) { y0.r = (breal) y0.i; } - breal x = x0.r, y = y0.r; -#else // CONFIG_IDF_TARGET_ESP32 - breal x = var2real(a), y = var2real(b); -#endif // CONFIG_IDF_TARGET_ESP32 - if (y == cast(breal, 0)) { - vm_error(vm, "divzero_error", "division by zero"); - } else { - var_setreal(dst, x / y); - } - } else if (var_isinstance(a)) { - ins_binop(vm, "/", ins); - } else { - binop_error(vm, "/", a, b); - } - dispatch(); - } - opcase(MOD): { - bvalue *dst = RA(), *a = RKB(), *b = RKC(); - if (var_isint(a) && var_isint(b)) { - bint x = var_toint(a), y = var_toint(b); - if (y == 0) { - vm_error(vm, "divzero_error", "division by zero"); - } else { - var_setint(dst, x % y); - } - } else if (var_isnumber(a) && var_isnumber(b)) { -#if CONFIG_IDF_TARGET_ESP32 /* when running on ESP32 in IRAM, there is a bug in early chip revision */ - union bvaldata x0, y0; // TASMOTA workaround for ESP32 rev0 bug - x0.i = a->v.i; - if (var_isint(a)) { x0.r = (breal) x0.i; } - y0.i = b->v.i; - if (var_isint(b)) { y0.r = (breal) y0.i; } - breal x = x0.r, y = y0.r; -#else - breal x = var2real(a), y = var2real(b); -#endif - if (y == cast(breal, 0)) { - vm_error(vm, "divzero_error", "division by zero"); - } else { - var_setreal(dst, mathfunc(fmod)(x, y)); - } - } else if (var_isinstance(a)) { - ins_binop(vm, "%", ins); - } else { - binop_error(vm, "%", a, b); - } - dispatch(); - } - opcase(LT): { - bbool res = be_vm_islt(vm, RKB(), RKC()); - bvalue *dst; - reg = vm->reg; - dst = RA(); - var_setbool(dst, res); - dispatch(); - } - opcase(LE): { - bbool res = be_vm_isle(vm, RKB(), RKC()); - bvalue *dst; - reg = vm->reg; - dst = RA(); - var_setbool(dst, res); - dispatch(); - } - opcase(EQ): { - bbool res = be_vm_iseq(vm, RKB(), RKC()); - bvalue *dst; - reg = vm->reg; - dst = RA(); - var_setbool(dst, res); - dispatch(); - } - opcase(NE): { - bbool res = be_vm_isneq(vm, RKB(), RKC()); - bvalue *dst; - reg = vm->reg; - dst = RA(); - var_setbool(dst, res); - dispatch(); - } - opcase(GT): { - bbool res = be_vm_isgt(vm, RKB(), RKC()); - bvalue *dst; - reg = vm->reg; - dst = RA(); - var_setbool(dst, res); - dispatch(); - } - opcase(GE): { - bbool res = be_vm_isge(vm, RKB(), RKC()); - bvalue *dst; - reg = vm->reg; - dst = RA(); - var_setbool(dst, res); - dispatch(); - } - opcase(CONNECT): { - bvalue *a = RKB(), *b = RKC(); - if (var_isint(a) && var_isint(b)) { - make_range(vm, *RKB(), *RKC()); - } else if (var_isstr(a)) { - connect_str(vm, var_tostr(a), b); - } else if (var_isinstance(a)) { - object_binop(vm, "..", *RKB(), *RKC()); - } else { - binop_error(vm, "..", RKB(), RKC()); - } - reg = vm->reg; - *RA() = *vm->top; /* copy result to R(A) */ - dispatch(); - } - opcase(AND): { - bitwise_block(&); - dispatch(); - } - opcase(OR): { - bitwise_block(|); - dispatch(); - } - opcase(XOR): { - bitwise_block(^); - dispatch(); - } - opcase(SHL): { - bitwise_block(<<); - dispatch(); - } - opcase(SHR): { - bitwise_block(>>); - dispatch(); - } - opcase(NEG): { - bvalue *dst = RA(), *a = RKB(); - if (var_isint(a)) { - var_setint(dst, -a->v.i); - } else if (var_isreal(a)) { - var_setreal(dst, -a->v.r); - } else if (var_isinstance(a)) { - ins_unop(vm, "-*", *RKB()); - reg = vm->reg; - *RA() = *vm->top; /* copy result to dst */ - } else { - unop_error(vm, "-", a); - } - dispatch(); - } - opcase(FLIP): { - bvalue *dst = RA(), *a = RKB(); - if (var_isint(a)) { - var_setint(dst, ~a->v.i); - } else if (var_isinstance(a)) { - ins_unop(vm, "~", *RKB()); - reg = vm->reg; - *RA() = *vm->top; /* copy result to dst */ - } else { - unop_error(vm, "~", a); - } - dispatch(); - } - opcase(JMP): { - vm->ip += IGET_sBx(ins); - dispatch(); - } - opcase(JMPT): { - if (be_value2bool(vm, RA())) { - vm->ip += IGET_sBx(ins); - } - dispatch(); - } - opcase(JMPF): { - if (!be_value2bool(vm, RA())) { - vm->ip += IGET_sBx(ins); - } - dispatch(); - } - opcase(CLOSURE): { - bvalue *dst; - bproto *p = clos->proto->ptab[IGET_Bx(ins)]; - bclosure *cl = be_newclosure(vm, p->nupvals); - cl->proto = p; - reg = vm->reg; - dst = RA(); - var_setclosure(dst, cl); - be_initupvals(vm, cl); - dispatch(); - } - opcase(CLASS): { - bclass *c = var_toobj(ktab + IGET_Bx(ins)); - be_class_upvalue_init(vm, c); - dispatch(); - } - opcase(GETMBR): { -#if BE_USE_PERF_COUNTERS - vm->counter_get++; -#endif - bvalue result; /* copy result to a temp variable because the stack may be relocated in virtual member calls */ - bvalue *b = RKB(), *c = RKC(); - if (var_isinstance(b) && var_isstr(c)) { - obj_attribute(vm, b, var_tostr(c), &result); - reg = vm->reg; - } else if (var_isclass(b) && var_isstr(c)) { - class_attribute(vm, b, c, &result); - reg = vm->reg; - } else if (var_ismodule(b) && var_isstr(c)) { - module_attribute(vm, b, c, &result); - reg = vm->reg; - } else { - attribute_error(vm, "attribute", b, c); - result = *RA(); /* avoid gcc warning for uninitialized variable result, this code is never reached */ - } - bvalue *a = RA(); - *a = result; /* assign the resul to the specified register on the updated stack */ - dispatch(); - } - opcase(GETMET): { -#if BE_USE_PERF_COUNTERS - vm->counter_get++; -#endif - bvalue result; /* copy result to a temp variable because the stack may be relocated in virtual member calls */ - bvalue *b = RKB(), *c = RKC(); - if (var_isinstance(b) && var_isstr(c)) { - binstance *obj = var_toobj(b); - int type = obj_attribute(vm, b, var_tostr(c), &result); - reg = vm->reg; - bvalue *a = RA(); - *a = result; - if (var_basetype(a) == BE_FUNCTION) { - if ((type & BE_STATIC) || (type == BE_INDEX)) { /* if instance variable then we consider it's non-method */ - /* static method, don't bother with the instance */ - a[1] = result; - var_settype(a, NOT_METHOD); - } else { - /* this is a real method (i.e. non-static) */ - /* check if the object is a superinstance, if so get the lowest possible subclass */ - while (obj->sub) { - obj = obj->sub; - } - var_setinstance(&a[1], obj); /* replace superinstance by lowest subinstance */ - } - } else if (var_isclass(a)) { - /* in this case we have a class in a static or non-static member */ - /* it's always treated like a static function */ - a[1] = result; - var_settype(a, NOT_METHOD); - } else { - vm_error(vm, "attribute_error", - "class '%s' has no method '%s'", - str(be_instance_name(obj)), str(var_tostr(c))); - } - } else if (var_isclass(b) && var_isstr(c)) { - class_attribute(vm, b, c, &result); - reg = vm->reg; - bvalue *a = RA(); - a[1] = result; - var_settype(a, NOT_METHOD); - } else if (var_ismodule(b) && var_isstr(c)) { - module_attribute(vm, b, c, &result); - reg = vm->reg; - bvalue *a = RA(); - a[1] = result; - var_settype(a, NOT_METHOD); - } else { - attribute_error(vm, "method", b, c); - } - dispatch(); - } - opcase(SETMBR): { -#if BE_USE_PERF_COUNTERS - vm->counter_set++; -#endif - bvalue *a = RA(), *b = RKB(), *c = RKC(); - if (var_isinstance(a) && var_isstr(b)) { - binstance *obj = var_toobj(a); - bstring *attr = var_tostr(b); - bvalue result = *c; - if (var_isfunction(&result)) { - var_markstatic(&result); - } - if (!be_instance_setmember(vm, obj, attr, &result)) { - reg = vm->reg; - vm_error(vm, "attribute_error", - "class '%s' cannot assign to attribute '%s'", - str(be_instance_name(obj)), str(attr)); - } - reg = vm->reg; - dispatch(); - } - if (var_isclass(a) && var_isstr(b)) { - /* if value is a function, we mark it as a static to distinguish from methods */ - bclass *obj = var_toobj(a); - bstring *attr = var_tostr(b); - bvalue result = *c; - if (var_isfunction(&result)) { - var_markstatic(&result); - } - if (!be_class_setmember(vm, obj, attr, &result)) { - reg = vm->reg; - vm_error(vm, "attribute_error", - "class '%s' cannot assign to static attribute '%s'", - str(be_class_name(obj)), str(attr)); - } - reg = vm->reg; - dispatch(); - } - if (var_ismodule(a) && var_isstr(b)) { - bmodule *obj = var_toobj(a); - bstring *attr = var_tostr(b); - if (be_module_setmember(vm, obj, attr, c)) { - reg = vm->reg; - dispatch(); - } else { - reg = vm->reg; - // fall through exception below - } - } - attribute_error(vm, "writable attribute", a, b); - dispatch(); - } - opcase(GETIDX): { - bvalue *b = RKB(), *c = RKC(); - if (var_isinstance(b)) { - bvalue *top = vm->top; - /* get method 'item' */ - obj_method(vm, b, str_literal(vm, "item"), vm->top); - top[1] = *b; /* move object to argv[0] */ - top[2] = *c; /* move key to argv[1] */ - vm->top += 3; /* prevent collection results */ - be_dofunc(vm, top, 2); /* call method 'item' */ - vm->top -= 3; - reg = vm->reg; - *RA() = *vm->top; /* copy result to R(A) */ - } else if (var_isstr(b)) { - bstring *s = be_strindex(vm, var_tostr(b), c); - reg = vm->reg; - var_setstr(RA(), s); - } else { - vm_error(vm, "type_error", - "value '%s' does not support subscriptable", - be_vtype2str(b)); - } - dispatch(); - } - opcase(SETIDX): { - bvalue *a = RA(), *b = RKB(), *c = RKC(); - if (var_isinstance(a)) { - bvalue *top = vm->top; - /* get method 'setitem' */ - obj_method(vm, a, str_literal(vm, "setitem"), vm->top); - top[1] = *a; /* move object to argv[0] */ - top[2] = *b; /* move key to argv[1] */ - top[3] = *c; /* move src to argv[2] */ - vm->top += 4; - be_dofunc(vm, top, 3); /* call method 'setitem' */ - vm->top -= 4; - reg = vm->reg; - } else { - vm_error(vm, "type_error", - "value '%s' does not support index assignment", - be_vtype2str(a)); - } - dispatch(); - } - opcase(SETSUPER): { - bvalue *a = RA(), *b = RKB(); - if (var_isclass(a) && var_isclass(b)) { - bclass *obj = var_toobj(a); - if (!gc_isconst(obj)) { - be_class_setsuper(obj, var_toobj(b)); - } else { - vm_error(vm, "internal_error", - "cannot change superclass of a read-only class"); - } - } else { - vm_error(vm, "type_error", - "value '%s' does not support set super", - be_vtype2str(b)); - } - dispatch(); - } - opcase(CLOSE): { - be_upvals_close(vm, RA()); - dispatch(); - } - opcase(IMPORT): { - bvalue *b = RKB(); - if (var_isstr(b)) { - bstring *name = var_tostr(b); - int res = be_module_load(vm, name); - reg = vm->reg; - switch (res) { - case BE_OK: /* find the module */ - be_stackpop(vm, 1); - *RA() = *vm->top; - break; - case BE_EXCEPTION: /* pop the exception value and message */ - be_pop(vm, 2); - be_throw(vm, BE_EXCEPTION); - break; - default: - vm_error(vm, "import_error", "module '%s' not found", str(name)); - } - } else { - vm_error(vm, "type_error", - "import '%s' does not support import", - be_vtype2str(b)); - } - dispatch(); - } - opcase(CATCH): { - bvalue *base = RA(), *top = vm->top; - int i = 0, ecnt = IGET_RKB(ins), vcnt = IGET_RKC(ins); - while (i < ecnt && !be_vm_iseq(vm, top, base + i)) { - ++i; - } - if (!ecnt || i < ecnt) { /* exception catched */ - base = RA(), top = vm->top; - for (i = 0; i < vcnt; ++i) { - *base++ = *top++; - } - vm->ip += 1; /* skip next instruction */ - } - dispatch(); - } - opcase(RAISE): { - if (IGET_RA(ins) < 2) { /* A==2 means no arguments are passed to RAISE, i.e. rethrow with current exception */ - bvalue *top = vm->top; - top[0] = *RKB(); /* push the exception value to top */ - if (IGET_RA(ins)) { /* has exception argument? */ - top[1] = *RKC(); /* push the exception argument to top + 1 */ - } else { - var_setnil(top + 1); - } - be_save_stacktrace(vm); - } - be_throw(vm, BE_EXCEPTION); /* throw / rethrow the exception */ - dispatch(); - } - opcase(EXBLK): { -#if BE_USE_PERF_COUNTERS - vm->counter_try++; -#endif - if (!IGET_RA(ins)) { - be_except_block_setup(vm); - if (be_setjmp(vm->errjmp->b)) { - bvalue *top = vm->top; - bvalue e1 = top[0]; - bvalue e2 = top[1]; - be_except_block_resume(vm); - top = vm->top; - top[0] = e1; - top[1] = e2; - goto newframe; - } - reg = vm->reg; - } else { - be_except_block_close(vm, IGET_Bx(ins)); - } - dispatch(); - } - opcase(CALL): { -#if BE_USE_PERF_COUNTERS - vm->counter_call++; -#endif - bvalue *var = RA(); /* `var` is the register for the call followed by arguments */ - int mode = 0, argc = IGET_RKB(ins); /* B contains number of arguments pushed on stack */ - recall: /* goto: instantiation class and call constructor */ - switch (var_type(var)) { - case NOT_METHOD: - var[0] = var[1]; - ++var, --argc, mode = 1; - goto recall; - case BE_CLASS: - if (be_class_newobj(vm, var_toobj(var), var - reg, ++argc, mode)) { /* instanciate object and find constructor */ - reg = vm->reg + mode; /* constructor found */ - mode = 0; - var = RA() + 1; /* to next register */ - reg = vm->reg; - goto recall; /* call constructor */ - } - break; - case BE_INSTANCE: { - bvalue *v = var + argc++, temp; - /* load the '()' method to `temp' */ - obj_method(vm, var, str_literal(vm, "()"), &temp); - for (; v >= var; --v) v[1] = v[0]; - *var = temp; - goto recall; /* call '()' method */ - } - case BE_CLOSURE: { - prep_closure(vm, var - reg, argc, mode); - reg = vm->reg; /* `reg` has changed, now new base register */ - goto newframe; /* continue execution of the closure */ - } - case BE_NTVCLOS: { - bntvclos *f = var_toobj(var); - push_native(vm, var, argc, mode); - f->f(vm); /* call C primitive function */ - ret_native(vm); - break; - } - case BE_NTVFUNC: { - bntvfunc f = var_tontvfunc(var); - push_native(vm, var, argc, mode); - f(vm); /* call C primitive function */ - ret_native(vm); - break; - } - case BE_CTYPE_FUNC: { - if (vm->ctypefunc) { - push_native(vm, var, argc, mode); - const void* args = var_toobj(var); - vm->ctypefunc(vm, args); - ret_native(vm); - } else { - vm_error(vm, "internal_error", "missing ctype_func handler"); - } - break; - } - case BE_MODULE: { - bvalue attr; - var_setstr(&attr, str_literal(vm, "()")); - module_attribute(vm, var, &attr, var); /* exception if not found */ - goto recall; /* call '()' method */ - break; - } - default: - call_error(vm, var); - } - reg = vm->reg; - dispatch(); - } - opcase(RET): { - bcallframe *cf; - bvalue *ret; -#if BE_USE_DEBUG_HOOK - be_callhook(vm, BE_HOOK_RET); -#endif - cf = vm->cf; - ret = vm->cf->func; - /* copy return value */ - if (IGET_RA(ins)) { - *ret = *RKB(); - } else { - var_setnil(ret); - } - vm->reg = cf->reg; - vm->top = cf->top; - vm->ip = cf->ip; - be_stack_pop(&vm->callstack); /* pop don't delete */ - if (cf->status & BASE_FRAME) { /* entrance function */ - bstack *cs = &vm->callstack; - if (!be_stack_isempty(cs)) { - vm->cf = be_stack_top(cs); - } - return; - } - vm->cf = be_stack_top(&vm->callstack); - goto newframe; - } - } -} - -static void prep_closure(bvm *vm, int pos, int argc, int mode) -{ - bvalue *v, *end; - bproto *proto = var2cl(vm->reg + pos)->proto; - push_closure(vm, vm->reg + pos, proto->nstack, mode); - end = vm->reg + proto->argc; - for (v = vm->reg + argc; v <= end; ++v) { - var_setnil(v); - } - int v_offset = v - vm->stack; /* offset from stack base, stack may be reallocated */ - if (proto->varg & BE_VA_VARARG) { /* there are vararg at the last argument, build the list */ - /* code below uses mostly low-level calls for performance */ - be_stack_require(vm, argc + 4); /* make sure we don't overflow the stack */ - int top_save_offset = vm->top - vm->stack; /* save original stack, we need fresh slots to create the 'list' instance */ - vm->top = vm->stack + v_offset; /* move top of stack right after last argument */ - be_newobject(vm, "list"); /* this creates 2 objects on stack: list instance, BE_LIST object */ - blist *list = var_toobj(vm->top-1); /* get low-level BE_LIST structure */ - v = vm->reg + proto->argc - 1; /* last argument */ - for (; v < vm->reg + argc; v++) { - be_list_push(vm, list, v); /* push all varargs into list */ - } - *(vm->reg + proto->argc - 1) = *(vm->top-2); /* change the vararg argument to now contain the list instance */ - vm->top = vm->stack + top_save_offset; /* restore top of stack pointer */ - } -} - -static void do_closure(bvm *vm, int pos, int argc) -{ - // bvalue *v, *end; - // bproto *proto = var2cl(reg)->proto; - // push_closure(vm, reg, proto->nstack, 0); - // v = vm->reg + argc; - // end = vm->reg + proto->argc; - // for (; v <= end; ++v) { - // var_setnil(v); - // } - prep_closure(vm, pos, argc, 0); - vm_exec(vm); -} - -static void do_ntvclos(bvm *vm, int pos, int argc) -{ - bntvclos *f = var_toobj(vm->reg + pos); - push_native(vm, vm->reg + pos, argc, 0); - f->f(vm); /* call C primitive function */ - ret_native(vm); -} - -static void do_ntvfunc(bvm *vm, int pos, int argc) -{ - bntvfunc f = var_tontvfunc(vm->reg + pos); - push_native(vm, vm->reg + pos, argc, 0); - f(vm); /* call C primitive function */ - ret_native(vm); -} - -static void do_cfunc(bvm *vm, int pos, int argc) -{ - if (vm->ctypefunc) { - const void* args = var_toobj(vm->reg + pos); - push_native(vm, vm->reg + pos, argc, 0); - vm->ctypefunc(vm, args); - ret_native(vm); - } else { - vm_error(vm, "internal_error", "missing ctype_func handler"); - } -} - -static void do_class(bvm *vm, int pos, int argc) -{ - if (be_class_newobj(vm, var_toobj(vm->reg + pos), pos, ++argc, 0)) { - be_incrtop(vm); - be_dofunc(vm, vm->reg + pos + 1, argc); - be_stackpop(vm, 1); - } -} - -void be_dofunc(bvm *vm, bvalue *v, int argc) -{ - be_assert(vm->reg <= v && v < vm->stacktop); - be_assert(vm->stack <= vm->reg && vm->reg < vm->stacktop); - int pos = v - vm->reg; - be_assert(!var_isstatic(v)); - switch (var_type(v)) { - case BE_CLASS: do_class(vm, pos, argc); break; - case BE_CLOSURE: do_closure(vm, pos, argc); break; - case BE_NTVCLOS: do_ntvclos(vm, pos, argc); break; - case BE_NTVFUNC: do_ntvfunc(vm, pos, argc); break; - case BE_CTYPE_FUNC: do_cfunc(vm, pos, argc); break; - default: call_error(vm, v); - } -} - -/* Default empty constructor */ -int be_default_init_native_function(bvm *vm) -{ - int argc = be_top(vm); - if (argc >= 1) { - be_pushvalue(vm, 1); - } else { - be_pushnil(vm); - } - be_return(vm); -} - -BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook) -{ - (void)vm; /* avoid comiler warning */ - (void)hook; /* avoid comiler warning */ - - vm->obshook = hook; -} - -BERRY_API void be_set_obs_micros(bvm *vm, bmicrosfnct micros) -{ - vm->microsfnct = micros; -} - -BERRY_API void be_set_ctype_func_hanlder(bvm *vm, bctypefunc handler) -{ - vm->ctypefunc = handler; -} - -BERRY_API bctypefunc be_get_ctype_func_hanlder(bvm *vm) -{ - return vm->ctypefunc; -} diff --git a/lib/libesp32/Berry/src/be_vm.h b/lib/libesp32/Berry/src/be_vm.h deleted file mode 100644 index 5953a46251a1..000000000000 --- a/lib/libesp32/Berry/src/be_vm.h +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************** -** Copyright (c) 2018-2020 Guan Wenliang -** This file is part of the Berry default interpreter. -** skiars@qq.com, https://github.com/Skiars/berry -** See Copyright Notice in the LICENSE file or at -** https://github.com/Skiars/berry/blob/master/LICENSE -********************************************************************/ -#ifndef BE_VM_H -#define BE_VM_H - -#include "be_object.h" - -#define comp_is_named_gbl(vm) ((vm)->compopt & (1<compopt |= (1<compopt &= ~(1<compopt & (1<compopt |= (1<compopt &= ~(1<compopt & (1<compopt |= (1<compopt &= ~(1< -#include - -#include "berry_conf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @def BERRY_VERSION - * @brief do not modify the version number! - * - */ -#define BERRY_VERSION "1.1.0" - -#if BE_STACK_TOTAL_MAX < BE_STACK_FREE_MIN * 2 -#error "The value of the macro BE_STACK_TOTAL_MAX is too small." -#endif - -#if BE_INTGER_TYPE == 0 - #define BE_INTEGER int /**< BE_INTEGER */ - #define BE_INT_FMTLEN "" /**< BE_INT_FMTLEN */ -#elif BE_INTGER_TYPE == 1 - #define BE_INTEGER long /**< BE_INTEGER */ - #define BE_INT_FMTLEN "l" /**< BE_INT_FMTLEN */ -#elif BE_INTGER_TYPE == 2 -#ifdef _WIN32 - #define BE_INTEGER __int64 /**< BE_INTEGER */ - #define BE_INT_FMTLEN "I64" /**< BE_INT_FMTLEN */ - #else -#define BE_INTEGER long long /**< BE_INTEGER */ -#define BE_INT_FMTLEN "ll" /**< BE_INT_FMTLEN*/ -#endif -#else - #error "Unsupported integer type for `bint`." -#endif -#define BE_INT_FORMAT "%" BE_INT_FMTLEN "d" /**< BE_INT_FORMAT */ - -typedef uint8_t bbyte; /**< bbyte */ -typedef BE_INTEGER bint; /**< bint */ - -#if BE_USE_SINGLE_FLOAT != 0 - typedef float breal; /**< breal */ -#else -typedef double breal; /**< breal */ -#endif - - - -#ifndef __cplusplus -#define bbool _Bool /**< bbool */ -#define bfalse 0 /**< bfalse */ -#define btrue 1 /**< btrue */ -#else - #define bbool bool /**< bbool */ - #define bfalse false /**< bfalse */ - #define btrue true /**< btrue */ -#endif - -/** - * @enum berrorcode - * @brief error code definition - * - */ -enum berrorcode { - BE_OK = 0, /**< BE_OK */ - BE_EXIT, /**< BE_EXIT */ - BE_MALLOC_FAIL, /**< BE_MALLOC_FAIL */ - BE_EXCEPTION, /**< BE_EXCEPTION */ - BE_SYNTAX_ERROR, /**< BE_SYNTAX_ERROR */ - BE_EXEC_ERROR, /**< BE_EXEC_ERROR */ - BE_IO_ERROR /**< BE_IO_ERROR */ -}; - -/** - * @{ \name native-module member type specifier. - */ -/** - * \brief native-module member type specifier. - * - */ -#define BE_CNIL 0 /**< BE_CNIL */ -#define BE_CINT 1 /**< BE_CINT */ -#define BE_CREAL 2 /**< BE_CREAL */ -#define BE_CBOOL 3 /**< BE_CBOOL */ -#define BE_CFUNCTION 4 /**< BE_CFUNCTION */ -#define BE_CSTRING 5 /**< BE_CSTRING */ -#define BE_CMODULE 6 /**< BE_CMODULE */ -/** - * @} - */ - - -/** - * @def BERRY_API - * @brief API function mark - * - */ -#if defined(_WIN32) || defined(__CYGWIN__) /* in Windows */ - #if defined(BERRY_MODULE) /* berry extension module */ - #define BERRY_API __declspec(dllimport) - #else /* berry core */ - #define BERRY_API __declspec(dllexport) - #endif -#else /* other platforms */ - #define BERRY_API extern -#endif - -/** - * @{ \name only linux. - */ -/** - * \brief only linux - * - */ -#if defined(_WIN32) || defined(__CYGWIN__) /* in Windows */ - #define BERRY_LOCAL /**< BERRY_LOCAL */ -#elif defined(__GNUC__) /* in GCC */ -#define BERRY_LOCAL __attribute__ ((visibility ("hidden"))) /**< BERRY_LOCAL */ -#else /* other platforms */ - #define BERRY_LOCAL /**< BERRY_LOCAL */ -#endif - -#ifdef __cplusplus -#ifdef __cpp_constexpr - #define BE_CONSTEXPR constexpr /**< BE_CONSTEXPR */ -#else - #define BE_CONSTEXPR /**< BE_CONSTEXPR */ -#endif -#endif - -#ifdef __cplusplus -#define BE_EXPORT_VARIABLE extern "C" /**< BE_EXPORT_VARIABLE */ -#else -#define BE_EXPORT_VARIABLE /**< BE_EXPORT_VARIABLE */ -#endif -/** - * @} - */ - -/** - * @brief virtual machine structure - */ -typedef struct bvm bvm; - -typedef int (*bntvfunc)(bvm*); /**< native function pointer */ - -/** - * @struct bclass - * @brief bclass - */ -struct bclass; - -/** - * @struct bnfuncinfo - * @brief native function information - * - */ -typedef struct { - const char *name; /**< name */ - bntvfunc function; /**< function */ -} bnfuncinfo; - -/** - * @struct bntvmodobj - * @brief bntvmodobj - * - */ -typedef struct bntvmodobj { - const char *name; /**< name */ - int type; /**< type */ - union value /**< value */ - { - bint i; /**< i */ - breal r; /**< r */ - bbool b; /**< b */ - bntvfunc f; /**< f */ - const char *s; /**< s */ - const void *o; /**< o */ -#ifdef __cplusplus - BE_CONSTEXPR value(bint v) : i(v) {} /**< i */ - BE_CONSTEXPR value(breal v) : r(v) {} /**< r */ - BE_CONSTEXPR value(bbool v) : b(v) {} /**< b */ - BE_CONSTEXPR value(bntvfunc v) : f(v) {} /**< f */ - BE_CONSTEXPR value(const char *v) : s(v) {} /**< s */ - BE_CONSTEXPR value(const void *v) : o(v) {} /**< o */ -#endif - } u; /**< u */ -#ifdef __cplusplus - BE_CONSTEXPR bntvmodobj(const char *name) : - name(name), type(BE_CNIL), u(bint(0)) {} /**< bntvmodobj */ - BE_CONSTEXPR bntvmodobj(const char *name, bint v) : - name(name), type(BE_CINT), u(v) {} /**< bntvmodobj */ - BE_CONSTEXPR bntvmodobj(const char *name, breal v) : - name(name), type(BE_CREAL), u(v) {} /**< bntvmodobj */ - BE_CONSTEXPR bntvmodobj(const char *name, bbool v) : - name(name), type(BE_CBOOL), u(v) {} /**< bntvmodobj */ - BE_CONSTEXPR bntvmodobj(const char *name, bntvfunc v) : - name(name), type(BE_CFUNCTION), u(v) {} /**< bntvmodobj */ - BE_CONSTEXPR bntvmodobj(const char *name, const char *v) : - name(name), type(BE_CSTRING), u(v) {} /**< bntvmodobj */ - BE_CONSTEXPR bntvmodobj(const char *name, int _tpye, const void *v) : - name(name), type(_tpye), u(v) {} /**< bntvmodobj */ -#endif -} bntvmodobj_t; /**< bntvmodobj_t */ - -/** - * @struct bntvmodule - * @brief bntvmodule - * - */ -typedef struct bntvmodule { - const char *name; /**< native module name */ - const bntvmodobj_t *attrs; /**< native module attributes */ - size_t size; /**< native module attribute count */ - const struct bmodule *module; /**< const module object */ -} bntvmodule_t; /**< bntvmodule_t */ - -/** - * @struct bclass - * @brief native class object - */ -struct bclass; - -/** - * @brief we need only the pointer to `bclass` here - */ -typedef const struct bclass *bclass_ptr; - -/** - * @brief array of bclass* pointers, NULL terminated - */ -typedef bclass_ptr bclass_array[]; - -/** - * @def be_native_module_nil - * @brief native module node definition macro - * - */ -#ifndef __cplusplus -#define be_native_module_nil(_name) \ - { .name = (_name), .type = BE_CNIL, .u.i = 0 } - -/** - * @def be_native_module_int - * @brief be_native_module_int - * - */ -#define be_native_module_int(_name, _v) \ - { .name = (_name), .type = BE_CINT, .u.i = (bint)(_v) } - -/** - * @def be_native_module_real - * @brief be_native_module_real - * - */ -#define be_native_module_real(_name, _v) \ - { .name = (_name), .type = BE_CREAL, .u.r = (breal)(_v) } - -/** - * @def be_native_module_bool - * @brief be_native_module_bool - * - */ -#define be_native_module_bool(_name, _b) \ - { .name = (_name), .type = BE_CBOOL, .u.b = (bbool)(_b) } - -/** - * @def be_native_module_function - * @brief be_native_module_function - * - */ -#define be_native_module_function(_name, _f) \ - { .name = (_name), .type = BE_CFUNCTION, .u.f = (_f) } - -/** - * @def be_native_module_str - * @brief be_native_module_str - * - */ -#define be_native_module_str(_name, _s) \ - { .name = (_name), .type = BE_CSTRING, .u.s = (_s) } - -/** - * @def be_native_module_module - * @brief be_native_module_module - * - */ -#define be_native_module_module(_name, _m) \ - { .name = (_name), .type = BE_CMODULE, .u.o = &(_m) } -#else - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_nil(_name) \ - bntvmodobj(_name) - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_int(_name, _v) \ - bntvmodobj(_name, bint(_v)) - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_real(_name, _v) \ - bntvmodobj(_name, breal(_v)) - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_bool(_name, _b) \ - bntvmodobj(_name, bbool(_b)) - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_function(_name, _f) \ - bntvmodobj(_name, _f) - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_str(_name, _s) \ - bntvmodobj(_name, _s) - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_module(_name, _m) \ - bntvmodobj(_name, BE_CMODULE, &(_m)) -#endif - -/** - * @def be_native_module_attr_table - * @brief be_native_module_attr_table - * - */ -#define be_native_module_attr_table(name) \ - static const bntvmodobj name##_attrs[] = - -/** - * @def be_native_module - * @brief be_native_module - * - */ -#define be_native_module(name) be_native_module_##name - -/** - * @def be_native_class - * @brief be_native_class - * - */ -#define be_native_class(name) be_class_##name - -/** - * @def be_extern_native_module - * @brief native module declaration macro - * - */ -#define be_extern_native_module(name) \ - extern const bntvmodule_t be_native_module(name) - -/** - * @def be_extern_native_class - * @brief native class declaration macro - * - */ -#define be_extern_native_class(name) \ - extern const struct bclass be_native_class(name) - -/** - * @def be_define_native_module - * @brief native module definition macro - * - */ -#ifndef __cplusplus -#define be_define_native_module(_name, _init) \ - const bntvmodule be_native_module(_name) = { \ - .name = #_name, \ - .attrs = _name##_attrs, \ - .size = sizeof(_name##_attrs) \ - / sizeof(_name##_attrs[0]), \ - .module = NULL, \ - .init = _init \ - } -#else -#define be_define_native_module(_name, _init) \ - const bntvmodule be_native_module(_name) = { \ - #_name, _name##_attrs, \ - sizeof(_name##_attrs) \ - / sizeof(_name##_attrs[0]), \ - 0, _init \ - } -#endif - -/** - * @def be_define_local_const_str - * @brief support for solidified berry functions - * native const strings outside of global string hash - * - */ -#define be_define_local_const_str(_name, _s, _hash, _len) \ - static const bcstring be_local_const_str_##_name = { \ - .next = (bgcobject *)NULL, \ - .type = BE_STRING, \ - .marked = GC_CONST, \ - .extra = 0, \ - .slen = _len, \ - .hash = 0, \ - .s = _s \ - } - -/** - * @def be_nested_const_str - * @brief new version for more compact literals - * - */ -#define be_nested_const_str(_s, _hash, _len) \ - (bstring*) &(const bcstring) { \ - .next = (bgcobject *)NULL, \ - .type = BE_STRING, \ - .marked = GC_CONST, \ - .extra = 0, \ - .slen = _len, \ - .hash = 0, \ - .s = _s \ - } - -/** - * @def be_local_const_str - * @brief be_local_const_str - * - */ -#define be_local_const_str(_name) (bstring*) &be_local_const_str_##_name - -#define BE_IIF(cond) BE_IIF_ ## cond /**< conditional macro see https://stackoverflow.com/questions/11632219/c-preprocessor-macro-specialisation-based-on-an-argument */ -#define BE_IIF_0(t, f) f /**< conditional macro see https://stackoverflow.com/questions/11632219/c-preprocessor-macro-specialisation-based-on-an-argument */ -#define BE_IIF_1(t, f) t /**< conditional macro see https://stackoverflow.com/questions/11632219/c-preprocessor-macro-specialisation-based-on-an-argument */ - -/** - * @def be_local_const_upval - * @brief be_local_const_upval - * - */ -#if BE_DEBUG_VAR_INFO - #define be_local_const_upval(ins, idx) { "", ins, idx } -#else - #define be_local_const_upval(ins, idx) { ins, idx } -#endif - -/** - * @def BE_DEBUG_SOURCE_FILE - * @brief conditional block in bproto depending on compilation options - * - */ -#if BE_DEBUG_SOURCE_FILE - #define PROTO_SOURCE_FILE(n) \ - ((bstring*) n), /**< source */ - #define PROTO_SOURCE_FILE_STR(n) \ - be_local_const_str(n##_str_source), /**< source */ -#else - #define PROTO_SOURCE_FILE(n) - #define PROTO_SOURCE_FILE_STR(n) -#endif - -/** - * @def PROTO_RUNTIME_BLOCK - * @brief conditional block in bproto depending on compilation options - * - */ -#if BE_DEBUG_RUNTIME_INFO - #define PROTO_RUNTIME_BLOCK \ - NULL, /**< lineinfo */ \ - 0, /**< nlineinfo */ -#else - #define PROTO_RUNTIME_BLOCK -#endif - -/** - * @def PROTO_VAR_INFO_BLOCK - * @brief PROTO_VAR_INFO_BLOCK - * - */ -#if BE_DEBUG_VAR_INFO - #define PROTO_VAR_INFO_BLOCK \ - NULL, /**< varinfo */ \ - 0, /**< nvarinfo */ -#else - #define PROTO_VAR_INFO_BLOCK -#endif - -/** - * @def be_define_local_proto - * @brief define bproto - * - */ -#define be_define_local_proto(_name, _nstack, _argc, _is_const, _is_subproto, _is_upval) \ - static const bproto _name##_proto = { \ - NULL, /**< bgcobject *next */ \ - BE_PROTO, /**< type BE_PROTO */ \ - 0x08, /**< marked outside of GC */ \ - (_nstack), /**< nstack */ \ - BE_IIF(_is_upval)(sizeof(_name##_upvals)/sizeof(bupvaldesc),0), /**< nupvals */ \ - (_argc), /**< argc */ \ - 0, /**< varg */ \ - sizeof(_name##_code)/sizeof(uint32_t), /**< codesize */ \ - BE_IIF(_is_const)(sizeof(_name##_ktab)/sizeof(bvalue),0), /**< nconst */ \ - BE_IIF(_is_subproto)(sizeof(_name##_subproto)/sizeof(bproto*),0), /**< proto */ \ - NULL, /**< bgcobject *gray */ \ - BE_IIF(_is_upval)((bupvaldesc*)&_name##_upvals,NULL), /**< bupvaldesc *upvals */ \ - BE_IIF(_is_const)((bvalue*)&_name##_ktab,NULL), /**< ktab */ \ - BE_IIF(_is_subproto)((struct bproto**)&_name##_subproto,NULL), /**< bproto **ptab */ \ - (binstruction*) &_name##_code, /**< code */ \ - be_local_const_str(_name##_str_name), /**< name */ \ - PROTO_SOURCE_FILE_STR(_name) /**< source */ \ - PROTO_RUNTIME_BLOCK /**< */ \ - PROTO_VAR_INFO_BLOCK /**< */ \ - } - -/** - * @def be_nested_proto - * @brief new version for more compact literals - * - */ -#define be_nested_proto(_nstack, _argc, _varg, _has_upval, _upvals, _has_subproto, _protos, _has_const, _ktab, _fname, _source, _code) \ - & (const bproto) { \ - NULL, /**< bgcobject *next */ \ - BE_PROTO, /**< type BE_PROTO */ \ - 0x08, /**< marked outside of GC */ \ - (_nstack), /**< nstack */ \ - BE_IIF(_has_upval)(sizeof(*_upvals)/sizeof(bupvaldesc),0), /**< nupvals */ \ - (_argc), /**< argc */ \ - (_varg), /**< varg */ \ - sizeof(*_code)/sizeof(binstruction), /**< codesize */ \ - BE_IIF(_has_const)(sizeof(*_ktab)/sizeof(bvalue),0), /**< nconst */ \ - BE_IIF(_has_subproto)(sizeof(*_protos)/sizeof(bproto*),0), /**< proto */ \ - NULL, /**< bgcobject *gray */ \ - (bupvaldesc*) _upvals, /**< bupvaldesc *upvals */ \ - (bvalue*) _ktab, /**< ktab */ \ - (struct bproto**) _protos, /**< bproto **ptab */ \ - (binstruction*) _code, /**< code */ \ - ((bstring*) _fname), /**< name */ \ - PROTO_SOURCE_FILE(_source) /**< source */ \ - PROTO_RUNTIME_BLOCK /**< */ \ - PROTO_VAR_INFO_BLOCK /**< */ \ - } - -/** - * @def be_define_local_closure - * @brief be_define_local_closure - * - */ -#define be_define_local_closure(_name) \ - const bclosure _name##_closure = { \ - NULL, /**< bgcobject *next */ \ - BE_CLOSURE, /**< type BE_CLOSURE */ \ - GC_CONST, /**< marked GC_CONST */ \ - 0, /**< nupvals */ \ - NULL, /**< bgcobject *gray */ \ - (bproto*) &_name##_proto, /**< proto */ \ - { NULL } /**< upvals */ \ - } - -/** - * @def be_local_closure - * @brief new version for more compact literals - * - */ -#define be_local_closure(_name, _proto) \ - static const bclosure _name##_closure = { \ - NULL, /**< bgcobject *next */ \ - BE_CLOSURE, /**< type BE_CLOSURE */ \ - GC_CONST, /**< marked GC_CONST */ \ - 0, /**< nupvals */ \ - NULL, /**< bgcobject *gray */ \ - (bproto*) _proto, /**< proto */ \ - { NULL } /**< upvals */ \ - } - -/** - * @{ \name debug hook typedefs. - */ -/** - * \brief debug hook typedefs. - * - */ -#define BE_HOOK_LINE 1 /**< BE_HOOK_LINE */ -#define BE_HOOK_CALL 2 /**< BE_HOOK_CALL */ -#define BE_HOOK_RET 4 /**< BE_HOOK_RET */ -#define BE_HOOK_EXCEPT 8 /**< BE_HOOK_EXCEPT */ -/** - * @} - */ - -/** - * @struct bhookinfo - * @brief bhookinfo - * - */ -typedef struct bhookinfo { - int type; /**< current hook type */ - int line; /**< current line number */ - const char *source; /**< source path information */ - const char *func_name; /**< current function name */ - void *data; /**< user extended data */ -} bhookinfo_t; /**< bhookinfo_ */ - -/** - * @fn void (*bntvhook)(bvm *vm, bhookinfo *info) - * @brief void (*bntvhook)(bvm *vm, bhookinfo *info) - * - * @param vm virtual machine instance - * @param info - */ -typedef void (*bntvhook)(bvm *vm, bhookinfo_t *info); - -/** - * @def be_assert - * @brief the default assert definition - * - */ -#if !BE_DEBUG -#if defined(be_assert) -#undef be_assert -#endif -#define be_assert(expr) ((void)0) -#endif - -/** - * @fn void (*bobshook)(bvm *vm, int event, ...) - * @brief Observability hook - * - * @param vm virtual machine instance - * @param event - */ -typedef void (*bobshook)(bvm *vm, int event, ...); -typedef uint32_t(*bmicrosfnct)(void); - -/** - * @enum beobshookevents - * @brief beobshookevents - * - */ -enum beobshookevents { - BE_OBS_PCALL_ERROR, /**< called when be_callp() returned an error, most likely an exception */ - BE_OBS_GC_START, /**< start of GC, arg = allocated size */ - BE_OBS_GC_END, /**< end of GC, arg = allocated size */ - BE_OBS_VM_HEARTBEAT, /**< VM heartbeat called every million instructions */ - BE_OBS_STACK_RESIZE_START, /**< Berry stack resized */ - BE_OBS_MALLOC_FAIL, /**< Memory allocation failed */ -}; - -typedef int (*bctypefunc)(bvm*, const void*); /**< bctypefunc */ - -/** - * @def be_writestring - * @note FFI function - * @brief be_writestring - * - */ -#define be_writestring(s) be_writebuffer((s), strlen(s)) - -/** - * @def be_writenewline - * @note FFI function - * @brief be_writenewline - * - */ -#define be_writenewline() be_writebuffer("\n", 1) - -/** - * @def be_return - * @note FFI function - * @brief be_return - * - * @param vm virtual machine instance virtual machine instance - */ -#define be_return(vm) return be_returnvalue(vm) - -/** - * @def be_return_nil - * @note FFI function - * @brief be_return_nil - * - * @param vm virtual machine instance virtual machine instance - */ -#define be_return_nil(vm) return be_returnnilvalue(vm) - -/** - * @def be_loadfile - * @note FFI function - * @brief be_loadfile - * - * @param vm virtual machine instance virtual machine instance - * @param name (???) - */ -#define be_loadfile(vm, name) be_loadmode((vm), (name), 0) - -/** - * @def be_loadmodule - * @note FFI function - * @brief be_loadmodule - * - * @param vm virtual machine instance virtual machine instance - * @param name - * - */ -#define be_loadmodule(vm, name) be_loadmode((vm), (name), 1) - -/** - * @def be_loadstring - * @note FFI function - * @brief be_loadstring - * - * @param vm virtual machine instance virtual machine instance - * @param str (???) - * - */ -#define be_loadstring(vm, str) \ - be_loadbuffer((vm), "string", (str), strlen(str)) - -/** - * @def be_dostring - * @note FFI function - * @brief be_dostring - * - * @param vm virtual machine instance virtual machine instance - * @param s (???) - * - */ -#define be_dostring(vm, s) \ - (be_loadstring((vm), (s)) || be_pcall((vm), 0)) - -/** - * @fn bint be_str2int(const char*, const char**) - * @note FFI function - * @brief (???) - * - * @param str (???) - * @param endstr (???) - * @return (???) - */ -BERRY_API bint be_str2int(const char *str, const char **endstr); - -/** - * @fn breal be_str2real(const char*, const char**) - * @note FFI function - * @brief (???) - * - * @param str - * @param endstr (???) - * @return (???) - */ -BERRY_API breal be_str2real(const char *str, const char **endstr); - -/** - * @fn const char* be_str2num(bvm *vm, const char *str) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance virtual machine instance - * @param str (???) - * @return (???) - */ -BERRY_API const char* be_str2num(bvm *vm, const char *str); - -/** - * @fn int be_top(bvm*) - * @note FFI function - * @brief returns the absolute index value of the top element in the virtual stack - * - * This function returns the absolute index value of the top element in the virtual stack. - * This value is also the number of elements in the virtual stack (the capacity of the virtual stack). - * Call this function before adding or subtracting elements in the virtual stack to get the number of parameters of the native function. - * - * @param vm virtual machine instance virtual machine instance - * @return (???) - */ -BERRY_API int be_top(bvm *vm); - -/** - * @fn const char* be_typename(bvm *vm, int index) - * @note FFI function - * @brief converts the type of the Berry object into a string and returns it - * - * This function converts the type of the Berry object into a string and returns it. - * For example, it returns "int" for an integer object, and "function" for a function object. - * - * @param vm virtual machine instance virtual machine instance - * @param index index of the object to be operated - * @return string corresponding to the parameter type (see: baselib_type) - */ -BERRY_API const char* be_typename(bvm *vm, int index); - -/** - * @fn const char* be_classname(bvm *vm, int index) - * @note FFI function - * @brief converts the type of the Berry object into a string and returns it. - * - * This function converts the type of the Berry object into a string and returns it. - * For example, it returns "int" for an integer object, and "function" for a function object - * - * @param vm virtual machine instance virtual machine instance - * @param index index of the object to be operated - * @return string corresponding to the parameter type (see: baselib_type) - */ -BERRY_API const char* be_classname(bvm *vm, int index); - -/** - * @fn bool be_classof(bvm*, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance virtual machine instance - * @param index (???) - * @return (???) - */ -BERRY_API bbool be_classof(bvm *vm, int index); - -/** - * @fn int be_strlen(bvm*, int) - * @note FFI function - * @brief length of the specified Berry string - * - * This function returns the number of bytes in the string at index - * (the ’\0’ characters at the end of the Berry string are not counted). - * If the value of the index position is not a string, the be_strlen function will return 0. - * Although the Berry string is compatible with the C string format, - * it is not recommended to use the strlen function of the C standard library to measure the length of the Berry string. - * For Berry strings, be_strlen is faster than strlen and has better compatibility. - * - * @param vm virtual machine instance virtual machine instance - * @param index index of the object to be operated - * @return length - */ -BERRY_API int be_strlen(bvm *vm, int index); - -/** - * @fn void be_strconcat(bvm*, int) - * @note FFI function - * @brief splice two Berry strings - * - * This function will concatenate the string at the parameter position of index with the string at the top position of the stack, - * and then put the resulting string into the position indexed by index. - * - * @param vm virtual machine instance virtual machine instance - * @param index (???) - */ -BERRY_API void be_strconcat(bvm *vm, int index); - -/** - * @fn void be_pop(bvm*, int) - * @note FFI function - * @brief pops the value at the top of the stack - * - * Note that the value of n cannot exceed the capacity of the stack. - * - * @param vm virtual machine instance virtual machine instance - * @param n number of values to be popped - */ -BERRY_API void be_pop(bvm *vm, int n); - -/** - * @fn void be_remove(bvm*, int) - * @note FFI function - * @brief remove a value from the stack - * - * After the value at index is moved out, the following values will be filled forward, - * and the stack capacity will be reduced by one. - * The value of index cannot exceed the capacity of the stack. - * - * @param vm virtual machine instance virtual machine instance - * @param index the object to be removed - */ -BERRY_API void be_remove(bvm *vm, int index); - -/** - * @fn int be_absindex(bvm*, int) - * @note FFI function - * @brief absolute index value of a given index value - * - * If index is positive, the return value is the value of index. - * If index is negative, the return value of textttbe_absindex is the absolute index value corresponding to index. - * When index is a negative value (relative index), its index position cannot be lower than the bottom of the stack. - * - * @param vm virtual machine instance virtual machine instance - * @param index index value - * @return absolute index - */ -BERRY_API int be_absindex(bvm *vm, int index); - -/** - * @fn bool be_isnil(bvm*, int) - * @note FFI function - * @brief value in virtual stack is nil - * - * This function returns whether the value indexed by the parameter index in the virtual stack is nil, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isnil(bvm *vm, int index); - -/** - * @fn bool be_isbool(bvm*, int) - * @note FFI function - * @brief value in virtual stack is bool - * - * This function returns whether the value indexed by the parameter index in the virtual stack is bool, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isbool(bvm *vm, int index); - -/** - * @fn bool be_isint(bvm*, int) - * @note FFI function - * @brief value in virtual stack is int - * - * This function returns whether the value indexed by the parameter index in the virtual stack is int, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isint(bvm *vm, int index); - -/** - * @fn bool be_isreal(bvm*, int) - * @note FFI function - * @brief value in virtual stack is real - * - * This function returns whether the value indexed by the parameter index in the virtual stack is real, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isreal(bvm *vm, int index); - -/** - * @fn bool be_isnumber(bvm*, int) - * @note FFI function - * @brief value in virtual stack is number - * - * This function returns whether the value indexed by the parameter index in the virtual stack is number, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isnumber(bvm *vm, int index); - -/** - * @fn bool be_isstring(bvm*, int) - * @note FFI function - * @brief value in virtual stack is string - * - * This function returns whether the value indexed by the parameter index in the virtual stack is string, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isstring(bvm *vm, int index); - -/** - * @fn bool be_isclosure(bvm*, int) - * @note FFI function - * @brief value in virtual stack is closure - * - * This function returns whether the value indexed by the parameter index in the virtual stack is closure, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isclosure(bvm *vm, int index); - -/** - * @fn bool be_isntvclos(bvm*, int) - * @note FFI function - * @brief value in virtual stack is primitive closure type - * - * This function returns whether the value indexed by the parameter index in the virtual stack is primitive closure type, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isntvclos(bvm *vm, int index); - -/** - * @fn bool be_isfunction(bvm*, int) - * @note FFI function - * @brief value in virtual stack is function - * - * This function returns whether the value indexed by the parameter index in the virtual stack is function, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isfunction(bvm *vm, int index); - -/** - * @fn bool be_isproto(bvm*, int) - * @note FFI function - * @brief value in virtual stack is proto - * - * This function returns whether the value indexed by the parameter index in the virtual stack is proto, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isproto(bvm *vm, int index); - -/** - * @fn bool be_isclass(bvm*, int) - * @note FFI function - * @brief value in virtual stack is class - * - * This function returns whether the value indexed by the parameter index in the virtual stack is class, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isclass(bvm *vm, int index); - -/** - * @fn bool be_isinstance(bvm*, int) - * @note FFI function - * @brief value in virtual stack is instance - * - * This function returns whether the value indexed by the parameter index in the virtual stack is instance, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isinstance(bvm *vm, int index); - -/** - * @fn bool be_ismapinstance(bvm*, int) - * @note FFI function - * @brief value in virtual stack is instance - * - * This function returns whether the value indexed by the parameter index in the virtual stack is - * an instance of class map (or derived). If it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_ismapinstance(bvm *vm, int index); - -/** - * @fn bool be_ismapinstance(bvm*, int) - * @note FFI function - * @brief value in virtual stack is instance - * - * This function returns whether the value indexed by the parameter index in the virtual stack is - * an instance of class list (or derived). If it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_islistinstance(bvm *vm, int index); - -/** - * @fn bool be_ismodule(bvm*, int) - * @note FFI function - * @brief value in virtual stack is module - * - * This function returns whether the value indexed by the parameter index in the virtual stack is module, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_ismodule(bvm *vm, int index); - -/** - * @fn bool be_islist(bvm*, int) - * @note FFI function - * @brief value in virtual stack is list - * - * This function returns whether the value indexed by the parameter index in the virtual stack is list, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_islist(bvm *vm, int index); - -/** - * @fn bool be_ismap(bvm*, int) - * @note FFI function - * @brief value in virtual stack is map - * - * This function returns whether the value indexed by the parameter index in the virtual stack is map, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_ismap(bvm *vm, int index); - -/** - * @fn bool be_iscomptr(bvm*, int) - * @note FFI function - * @brief value in virtual stack is universal pointer type - * - * This function returns whether the value indexed by the parameter index in the virtual stack is universal pointer type, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_iscomptr(bvm *vm, int index); - -/** - * @fn bool be_iscomobj(bvm*, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_iscomobj(bvm *vm, int index); - -/** - * @fn bool be_isderived(bvm*, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isderived(bvm *vm, int index); - -/** - * @fn bool be_isbytes(bvm*, int) - * @note FFI function - * @brief value in virtual stack is instance or sub-instance of class bytes - * - * This function returns whether the value indexed by the parameter index in the virtual stack is instance or sub-instance of class bytes, - * if it is, it returns 1, otherwise it returns 0 - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return true/false - */ -BERRY_API bbool be_isbytes(bvm *vm, int index); - -/** - * @fn bint be_toint(bvm*, int) - * @note FFI function - * @brief virtual stack to integer type - * - * Get the value of the index position of index from the virtual stack and return it as an integer type. - * This function does not check the correctness of the type. - * If the value is an instance, the method toint() is called if it exists. - * - * @param vm virtual machine instance virtual machine instance - * @param index value index - * @return (???) - */ -BERRY_API bint be_toint(bvm *vm, int index); - -/** - * @fn breal be_toreal(bvm*, int) - * @note FFI function - * @brief virtual stack to floating-point number type - * - * Get the value of the index position of index from the virtual stack and return it as an floating-point number type. - * This function does not check the correctness of the type. - * - * @param vm virtual machine instance virtual machine instance - * @param index - * @return (???) - */ -BERRY_API breal be_toreal(bvm *vm, int index); - -/** - * @fn int be_toindex(bvm*, int) - * @note FFI function - * @brief virtual stack to integer type - * - * Get the value of the index position of index from the virtual stack and return it as an integer type. - * This function does not check the correctness of the type. - * Unlike be_toint, the return value type of be_toindex is int, while the return value of the former is bint. - * - * @param vm virtual machine instance virtual machine instance - * @param index - * @return (???) - */ -BERRY_API int be_toindex(bvm *vm, int index); - -/** - * @fn bool be_tobool(bvm*, int) - * @note FFI function - * @brief virtual stack to Boolean type - * - * Get the value of the index position of index from the virtual stack and return it as a Boolean type. - * If the indexed value is not of Boolean type, it will be converted according to the rules in section type_bool, - * and the conversion process will not cause the indexed value to change. - * If the value is an instance, the method tobool() is called if it exists. - * - * @param vm virtual machine instance virtual machine instance - * @param index - * @return (???) - */ -BERRY_API bbool be_tobool(bvm *vm, int index); - -/** - * @fn const char* be_tostring(bvm *vm, int index) - * @note FFI function - * @brief virtual stack to string - * - * Get the value of the index position of index from the virtual stack and return it as a string type. - * If the indexed value is not a string type, the indexed value will be converted to a string, - * and the conversion process will replace the value at the indexed position in the virtual stack with the converted string. - * The string returned by this function always ends with ’\0’ characters. - * If the value is an instance, the method tostring() is called if it exists. - * - * @param vm virtual machine instance virtual machine instance - * @param index - * @return (???) - */ -BERRY_API const char* be_tostring(bvm *vm, int index); - -/** - * @fn const char* be_toescape(bvm *vm, int index, int mode) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance virtual machine instance - * @param index - * @param mode - * @return (???) - */ -BERRY_API const char* be_toescape(bvm *vm, int index, int mode); - -/** - * @fn void* be_tocomptr(bvm *vm, int index) - * @note FFI function - * @brief virtual stack to general pointer - * - * Get the value of the index position of index from the virtual stack and return it as a general pointer type. - * This function does not check the correctness of the type. - * - * @param vm virtual machine instance virtual machine instance - * @param index - */ -BERRY_API void* be_tocomptr(bvm *vm, int index); - -/** - * @fn void be_moveto(bvm*, int, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance virtual machine instance - * @param from - * @param to - */ -BERRY_API void be_moveto(bvm *vm, int from, int to); - -/** - * @fn void be_pushnil(bvm*) - * @note FFI function - * @brief Push a nil value onto the virtual stack. - * - * @param vm virtual machine instance - * - */ -BERRY_API void be_pushnil(bvm *vm); - -/** - * @fn void be_pushbool(bvm*, int) - * @note FFI function - * @brief Push a Boolean value onto the virtual stack - * - * Push a Boolean value onto the virtual stack. - * The parameter b is the boolean value to be pushed onto the stack. - * When the value is 0, it means false, otherwise it is true. - * - * @param vm virtual machine instance - * @param b - */ -BERRY_API void be_pushbool(bvm *vm, int b); - -/** - * @fn void be_pushint(bvm*, bint) - * @note FFI function - * @brief Push an integer value i onto the virtual stack. - * - * @param vm virtual machine instance - * @param i - */ -BERRY_API void be_pushint(bvm *vm, bint i); - -/** - * @fn void be_pushreal(bvm*, breal) - * @note FFI function - * @brief Push a floating point value r onto the virtual stack. - * - * @param vm virtual machine instance - * @param r - */ -BERRY_API void be_pushreal(bvm *vm, breal r); - -/** - * @fn void be_pushstring(bvm*, const char*) - * @note FFI function - * @brief Push the string str onto the virtual stack. - * - * Push the string str onto the virtual stack. - * The parameter str must point to a C string that ends with a null character ’\0’, - * and a null pointer cannot be passed in. - * - * @param vm virtual machine instance - * @param str - */ -BERRY_API void be_pushstring(bvm *vm, const char *str); - -/** - * @fn void be_pushnstring(bvm*, const char*, size_t) - * @note FFI function - * @brief Push the string str of length n onto the virtual stack. - * - * Push the string str of length n onto the virtual stack. - * The length of the string is subject to the parameter n, - * and the null character is not used as the end mark of the string. - * - * @param vm virtual machine instance - * @param str - * @param n - */ -BERRY_API void be_pushnstring(bvm *vm, const char *str, size_t n); - -/** - * @fn const char* be_pushfstring(bvm *vm, const char *format, ...) - * @note FFI function - * @brief Push the formatted string into the virtual stack. - * - * Push the formatted string into the virtual stack. - * The parameter format is a formatted string, which contains the text to be pushed onto the stack, - * and the format parameter contains a label, - * which can be replaced by the value specified by the subsequent additional parameter and formatted as required. - * According to the label of the format string, a series of additional parameters may be required, - * and each additional parameter will replace the corresponding % label in the format parameter. - * - * @param vm virtual machine instance - * @param format - * @return (???) - */ -BERRY_API const char* be_pushfstring(bvm *vm, const char *format, ...); - -/** - * @fn void* be_pushbuffer(bvm *vm, size_t size) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param size - */ -BERRY_API void* be_pushbuffer(bvm *vm, size_t size); - -/** - * @fn void be_pushvalue(bvm*, int) - * @note FFI function - * @brief Push the value with index index onto the top of the virtual stack. - * - * @param vm virtual machine instance - * @param index - */ -BERRY_API void be_pushvalue(bvm *vm, int index); - -/** - * @fn void be_pushclosure(bvm*, void*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param cl - */ -BERRY_API void be_pushclosure(bvm *vm, void *cl); - -/** - * @fn void be_pushntvclosure(bvm*, bntvfunc, int) - * @note FFI function - * @brief Push a native closure onto the top of the virtual stack. - * - * Push a native closure onto the top of the virtual stack. - * The parameter f is the C function pointer of the native closure, - * and nupvals is the upvalue number of the closure. - * - * @param vm virtual machine instance - * @param f - * @param nupvals - */ -BERRY_API void be_pushntvclosure(bvm *vm, bntvfunc f, int nupvals); - -/** - * @fn void be_pushntvfunction(bvm*, bntvfunc) - * @note FFI function - * @brief Push a native function onto the top of the virtual stack, and the parameter f is the native function pointer. - * - * @param vm virtual machine instance - * @param f - */ -BERRY_API void be_pushntvfunction(bvm *vm, bntvfunc f); - -/** - * @fn void be_pushclass(bvm*, const char*, const bnfuncinfo*) - * @note FFI function - * @brief Push a native class onto the top of the virtual stack - * - * Push a native class onto the top of the virtual stack. - * The parameter name is the name of the native class, and the parameter lib is the attribute description of the native class. - * - * @param vm virtual machine instance - * @param name - * @param lib - */ -BERRY_API void be_pushclass(bvm *vm, const char *name, const bnfuncinfo *lib); - -/** - * @fn void be_pushntvclass(bvm*, const struct bclass*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param c - */ -BERRY_API void be_pushntvclass(bvm *vm, const struct bclass *c); - -/** - * @fn void be_pushcomptr(bvm*, void*) - * @note FFI function - * @brief Push a general pointer onto the top of the virtual stack - * - * Push a general pointer onto the top of the virtual stack. - * The general pointer ptr points to a certain C data area. - * Since the content pointed to by this pointer is not maintained by Berry’s garbage collector, - * users have to maintain the life cycle of the data themselves. - * - * @param vm virtual machine instance - * @param ptr - */ -BERRY_API void be_pushcomptr(bvm *vm, void *ptr); - -/** - * @fn bool be_pushiter(bvm*, int) - * @note FFI function - * @brief Push an iterator onto the top of the virtual stack. - * - * @param vm virtual machine instance - * @param index - * @return (???) - */ -BERRY_API bbool be_pushiter(bvm *vm, int index); - -/** - * @fn void be_newlist(bvm*) - * @note FFI function - * @brief creates a new list value - * - * After this function is successfully called, the new list value will be pushed onto the top of the stack. - * list value is an internal representation of a list, not to be confused with an instance of the list class. - * - * @param vm virtual machine instance - */ -BERRY_API void be_newlist(bvm *vm); - -/** - * @fn void be_newmap(bvm*) - * @note FFI function - * @brief creates a new map value - * - * After this function is successfully called, the new map value will be pushed onto the top of the stack. - * map value is an internal representation of a list, not to be confused with an instance of the map class. - * - * @param vm virtual machine instance - */ -BERRY_API void be_newmap(bvm *vm); - -/** - * @fn void be_newmodule(bvm*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - */ -BERRY_API void be_newmodule(bvm *vm); - -/** - * @fn void be_newcomobj(bvm*, void*, bntvfunc) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param data - * @param destroy - */ -BERRY_API void be_newcomobj(bvm *vm, void *data, bntvfunc destroy); - -/** - * @fn void be_newobject(bvm*, const char*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param name - */ -BERRY_API void be_newobject(bvm *vm, const char *name); - -/** - * @fn bool be_copy(bvm*, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param index - * @return - */ -BERRY_API bbool be_copy(bvm *vm, int index); - -/** - * @fn bool be_setname(bvm*, int, const char*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param index - * @param name - * @return (???) - */ -BERRY_API bbool be_setname(bvm *vm, int index, const char *name); - -/** - * @fn bool be_getglobal(bvm*, const char*) - * @note FFI function - * @brief pushes the global variable with the specified name onto the stack - * - * After this function is called, the global variable named name will be pushed onto the top of the virtual stack - * - * @param vm virtual machine instance - * @param name - * @return (???) - */ -BERRY_API bbool be_getglobal(bvm *vm, const char *name); - -/** - * @fn void be_setglobal(bvm*, const char*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param name - */ -BERRY_API void be_setglobal(bvm *vm, const char *name); - -/** - * @fn bool be_getbuiltin(bvm*, const char*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param name - * @return (???) - */ -BERRY_API bbool be_getbuiltin(bvm *vm, const char *name); - -/** - * @fn bool be_setmember(bvm*, int, const char*) - * @note FFI function - * @brief set the value of the member variable of the instance object class - * - * This function will copy the value at the top of the stack to the member k of the index position instance. - * Note that the top element of the stack will not pop up automatically. - * - * @param vm virtual machine instance - * @param index index of the instance object - * @param k name of the member - * @return (???) - */ -BERRY_API bbool be_setmember(bvm *vm, int index, const char *k); - -/** - * @fn bool be_getmember(bvm*, int, const char*) - * @note FFI function - * @brief get the value of the member variable of the instance object class - * - * This function pushes the value of the member of the index position instance k onto the top of the virtual stack. - * - * @param vm virtual machine instance - * @param index index of the instance object - * @param k name of the member - * @return (???) - */ -BERRY_API bbool be_getmember(bvm *vm, int index, const char *k); - -/** - * @fn bool be_getmethod(bvm*, int, const char*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param index - * @param k - * @return (???) - */ -BERRY_API bbool be_getmethod(bvm *vm, int index, const char *k); - -/** - * @fn bool be_getindex(bvm*, int) - * @note FFI function - * @brief get the value of list or map - * - * This function is used to get an element from the map or list container (internal values, not instances of map or list classes), - * and the index of the element is stored at the top of the stack (relative index is  − 1). - * After calling this function, the value obtained from the container will be pushed onto the top of the stack. - * If there is no subscript pointed to by the container, the value of nil will be pushed onto the top of the stack. - * - * @param vm virtual machine instance - * @param index index of the object to be operated - * @return (???) - */ -BERRY_API bbool be_getindex(bvm *vm, int index); - -/** - * @fn bool be_setindex(bvm*, int) - * @note FFI function - * @brief set a value in list or map - * - * This function is used to write an element of the map or list container. - * The index of the value to be written in the virtual stack is  − 1, - * and the index of the subscript of the write position in the virtual stack is  − 2. - * If the element with the specified subscript does not exist in the container, the write operation will fail. - * - * @param vm virtual machine instance - * @param index index of the object to be operated - * @return (???) - */ -BERRY_API bbool be_setindex(bvm *vm, int index); - -/** - * @fn void be_getupval(bvm*, int, int) - * @note FFI function - * @brief read an Up Value of the native closure - * - * The read Up Value will be pushed onto the top of the virtual stack. - * - * @param vm virtual machine instance - * @param index the native closure index value of the Up Value to be read - * @param pos position of the Up Value in the native closure Up Value table (numbering starts from 0) - */ -BERRY_API void be_getupval(bvm *vm, int index, int pos); - -/** - * @fn bool be_setupval(bvm*, int, int) - * @note FFI function - * @brief set an Up Value of the native closure. - * - * This function obtains a value from the top of the virtual stack and writes it to the target Up Value. - * After the operation is completed, the top value of the stack will not be popped from the stack. - * - * @param vm virtual machine instance - * @param index the native closure index value of the Up Value to be read - * @param pos position of the Up Value in the native closure Up Value table (numbering starts from 0) - * @return (???) - */ -BERRY_API bbool be_setupval(bvm *vm, int index, int pos); - -/** - * @fn bool be_setsuper(bvm*, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param index - * @return (???) - */ -BERRY_API bbool be_setsuper(bvm *vm, int index); - -/** - * @fn void be_getsuper(bvm*, int) - * @note FFI function - * @brief get the parent object of the base class or instance of the class. - * - * If the value at index is a class with a base class, the function will push its base class onto the top of the stack; - * if the value at index is an object with a parent object, - * the function will take its parent The object is pushed onto the top of the stack; otherwise, - * a value of nil is pushed onto the top of the stack. - * - * @param vm virtual machine instance - * @param index the class or object to be operated - */ -BERRY_API void be_getsuper(bvm *vm, int index); - -/** - * @fn int be_data_size(bvm*, int) - * @note FFI function - * @brief get the number of elements contained in the container - * - * If the value at index is a Map value or List value, - * the function returns the number of elements contained in the container, otherwise it returns -1. - * - * @param vm virtual machine instance - * @param index index of the container object to be operated - * @return (???) - */ -BERRY_API int be_data_size(bvm *vm, int index); - -/** - * @fn void be_data_push(bvm*, int) - * @note FFI function - * @brief append a new element to the end of the container. - * - * The object at index must be a List value. - * This function gets a value from the top of the stack and appends it to the end of the container. - * After the operation is completed, the value at the top of the stack will not be popped from the stack. - * - * @param vm virtual machine instance - * @param index index of the container object to be operate - */ -BERRY_API void be_data_push(bvm *vm, int index); - -/** - * @fn bool be_data_insert(bvm*, int) - * @note FFI function - * @brief insert a pair of elements into the container - * - * The object at index must be a List value or a Map value. - * The inserted element forms a pair of key-value pairs. - * The value is stored at the top of the stack, and the key is stored at the previous index on the top of the stack. - * It should be noted that the key inserted into the Map container cannot be a nil value, - * and the key inserted into the List container must be an integer value. - * If the operation is successful, the function will return bture, otherwise it will return bfalse. - * - * @param vm virtual machine instance - * @param index container object to be operated - * @return (???) - */ -BERRY_API bbool be_data_insert(bvm *vm, int index); - -/** - * @fn bool be_data_remove(bvm*, int) - * @note FFI function - * @brief remove an element in the container - * - * The object at index must be a List value or Map value. - * For the Map container, the key to delete the element is stored on the top of the virtual stack - * (need to be pressed before the function call); - * for the List container, the index of the element to be deleted is stored on the top of the virtual stack - * (need to be before the function call) push into). - * If the operation is successful, the function will return bture, otherwise it will return bfalse. - * - * @param vm virtual machine instance - * @param index container object to be operated. - * @return (???) - */ -BERRY_API bbool be_data_remove(bvm *vm, int index); - -/** - * @fn bool be_data_merge(bvm*, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param index - * @return (???) - */ -BERRY_API bbool be_data_merge(bvm *vm, int index); - -/** - * @fn void be_data_resize(bvm*, int) - * @note FFI function - * @brief reset the capacity of the container - * - * This function is only available for List containers, and the new capacity is stored on the top of the virtual stack (must be an integer). - * - * @param vm virtual machine instance - * @param index container object to be operated - */ -BERRY_API void be_data_resize(bvm *vm, int index); - -/** - * @fn void be_data_reverse(bvm*, int) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param index - */ -BERRY_API void be_data_reverse(bvm *vm, int index); - -/** - * @fn int be_iter_next(bvm*, int) - * @note FFI function - * @brief get the next element of the iterator - * - * The iterator object may be an iterator of a List container or a Map container. - * For the List iterator, this function pushes the iteration result value onto the top of the stack, - * while for the Map iterator, it pushes the key value into the previous position and the top of the stack respectively. - * Calling this function will update the iterator. - * If the function returns 0, the call fails, returning 1 to indicate that the current iterator is a List iterator, - * and returning 2 to indicate that the current iterator is a Map iterator. - * - * @param vm virtual machine instance - * @param index iterator to be operated - * @return (???) - */ -BERRY_API int be_iter_next(bvm *vm, int index); - -/** - * @fn bool be_iter_hasnext(bvm*, int) - * @note FFI function - * @brief test whether there is another element in the iterator - * - * The iterator object may be an iterator of a List container or a Map container. - * If there are more iterable elements in the iterator, return 1, otherwise return 0. - * - * @param vm virtual machine instance - * @param index iterator to be operated - * @return (???) - */ -BERRY_API bbool be_iter_hasnext(bvm *vm, int index); - -/** - * @fn bool be_refcontains(bvm*, int) - * @note FFI function - * @brief test whether there is a reference to the specified object in the reference stack - * - * This function is used to test whether there is a reference to the specified object in the reference stack. - * It must be used in conjunction with be_refpush and be_refpop. - * This API can avoid recursion when traversing objects that have their own references. - * This function is used for the value of an instance type. - * If there is a reference to the object in the reference stack, it returns 1, otherwise it returns 0. - * - * @param vm virtual machine instance - * @param index object to be operated - * @return (???) - */ -BERRY_API bbool be_refcontains(bvm *vm, int index); - -/** - * @fn void be_refpush(bvm*, int) - * @note FFI function - * @brief Push the reference of the specified object onto the reference stack. - * - * This function is used for the value of an instance type. - * - * @param vm virtual machine instance - * @param index object to be operated - */ -BERRY_API void be_refpush(bvm *vm, int index); - -/** - * @fn void be_refpop(bvm*) - * @note FFI function - * @brief Pop the object at the top of the reference stack - * - * This function is used in pairs with be_refpush - * - * @param vm virtual machine instance - */ -BERRY_API void be_refpop(bvm *vm); - -/** - * @fn void be_stack_require(bvm*, int) - * @note FFI function - * @brief tests the amount of free space on the stack and expands the stack space if it is insufficient - * - * If the free capacity of the virtual stack allocated by the VM to the native function is lower than this value, - * an expansion operation will be performed. - * - * @param vm virtual machine instance - * @param count required free stack capacity. - */ -BERRY_API void be_stack_require(bvm *vm, int count); - -/** - * @fn bool be_getmodule(bvm*, const char*) - * @note FFI function - * @brief (???) - * - * @param vm virtual machine instance - * @param k - * @return (???) - */ -BERRY_API bbool be_getmodule(bvm *vm, const char *k); - -/** - * @fn bool be_iseq(bvm*) - * @note relop operation API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API bbool be_iseq(bvm *vm); - -/** - * @fn bool be_isneq(bvm*) - * @note relop operation API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API bbool be_isneq(bvm *vm); - -/** - * @fn bool be_islt(bvm*) - * @note relop operation API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API bbool be_islt(bvm *vm); - -/** - * @fn bool be_isle(bvm*) - * @note relop operation API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API bbool be_isle(bvm *vm); - -/** - * @fn bool be_isgt(bvm*) - * @note relop operation API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API bbool be_isgt(bvm *vm); - -/** - * @fn bool be_isge(bvm*) - * @note relop operation API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API bbool be_isge(bvm *vm); - -/** - * @fn int be_returnvalue(bvm*) - * @note Function call/return API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API int be_returnvalue(bvm *vm); - -/** - * @fn int be_returnnilvalue(bvm*) - * @note Function call/return API - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API int be_returnnilvalue(bvm *vm); - -/** - * @fn void be_call(bvm*, int) - * @note Function call/return API - * @brief (???) - * - * @param vm virtual machine instance - * @param argc - */ -BERRY_API void be_call(bvm *vm, int argc); - -/** - * @fn int be_pcall(bvm*, int) - * @note Function call/return API - * @brief (???) - * - * @param vm virtual machine instance - * @param argc - * @return (???) - */ -BERRY_API int be_pcall(bvm *vm, int argc); - -/** - * @fn void be_exit(bvm*, int) - * @note Function call/return API - * @brief (???) - * - * @param vm virtual machine instance - * @param status - */ -BERRY_API void be_exit(bvm *vm, int status); - -/** - * @fn void be_raise(bvm*, const char*, const char*) - * @note exception API - * @brief (???) - * - * @param vm virtual machine instance - * @param except - * @param msg - */ -#ifdef __GNUC__ -__attribute__((noreturn)) -#endif -BERRY_API void be_raise(bvm *vm, const char *except, const char *msg); - -/** - * @fn int be_getexcept(bvm*, int) - * @note exception API - * @brief (???) - * - * @param vm virtual machine instance - * @param code - * @return (???) - */ -BERRY_API int be_getexcept(bvm *vm, int code); - -/** - * @fn void be_dumpvalue(bvm*, int) - * @note exception API - * @brief (???) - * - * @param vm virtual machine instance - * @param index - */ -BERRY_API void be_dumpvalue(bvm *vm, int index); - -/** - * @fn void be_dumpexcept(bvm*) - * @note exception API - * @brief (???) - * - * @param vm virtual machine instance - */ -BERRY_API void be_dumpexcept(bvm *vm); - -/** - * @fn void be_stop_iteration(bvm*) - * @note exception API - * @brief (???) - * - * @param vm virtual machine instance - */ -BERRY_API void be_stop_iteration(bvm *vm); - -/** - * @fn void be_regfunc(bvm*, const char*, bntvfunc) - * @note exception API - * @brief register a native function - * - * The specific behavior of this function is related to the value of the BE_USE_PRECOMPILED_OBJECT macro - * (although the FFI is still available when using the compile-time construction technique, - * it cannot dynamically register the built-in variables. - * In this case, please refer to the method of registering the built-in objects. - * - * @param vm virtual machine instance - * @param name name of the native function - * @param f pointer of the native function - */ -BERRY_API void be_regfunc(bvm *vm, const char *name, bntvfunc f); - -/** - * @fn void be_regclass(bvm*, const char*, const bnfuncinfo*) - * @note exception API - * @brief (???) - * - * @param vm virtual machine instance - * @param name - * @param lib - */ -BERRY_API void be_regclass(bvm *vm, const char *name, const bnfuncinfo *lib); - -/** - * @fn bvm* be_vm_new(void) - * @note VM management API - * @brief Construct a VM - * - * @return (???) - */ -BERRY_API bvm* be_vm_new(void); - -/** - * @fn void be_vm_delete(bvm*) - * @note VM management API - * @brief Destroy a VM - * - * @param vm virtual machine instance - */ -BERRY_API void be_vm_delete(bvm *vm); - -/** - * @fn void be_set_obs_hook(bvm*, bobshook) - * @note Observability hook - * @brief (???) - * - * @param vm virtual machine instance - * @param hook - */ -BERRY_API void be_set_obs_hook(bvm *vm, bobshook hook); -BERRY_API void be_set_obs_micros(bvm *vm, bmicrosfnct micros); - - -/** - * @fn void be_set_ctype_func_hanlder(bvm*, bctypefunc) - * @note Observability hook - * @brief (???) - * - * @param vm virtual machine instance - * @param handler - */ -BERRY_API void be_set_ctype_func_hanlder(bvm *vm, bctypefunc handler); - -/** - * @fn bctypefunc be_get_ctype_func_hanlder(bvm*) - * @note Observability hook - * @brief (???) - * - * @param vm virtual machine instance - * @return (???) - */ -BERRY_API bctypefunc be_get_ctype_func_hanlder(bvm *vm); - -/** - * @fn int be_loadbuffer(bvm*, const char*, const char*, size_t) - * @note code load API - * @brief load a piece of source code from the buffer and compile it into bytecode - * - * f the compilation is successful, be_loadbuffer will compile the source code into a Berry function and place - * it on the top of the virtual stack. If the compilation encounters an error, be_loadbuffer will return - * an error value of type berrorcode (Section errorcode), and if possible, will store the - * specific error message string at the top of the virtual stack. - * - * @param vm virtual machine instance - * @param name string, which is usually used to mark the source of the source code - * @param buffer buffer for storing the source code - * @param length length of the buffer - * @return (???) - */ -BERRY_API int be_loadbuffer(bvm *vm, const char *name, const char *buffer, size_t length); - -/** - * @fn int be_loadmode(bvm *vm, const char *name, bbool islocal) - * @note code load API - * @brief (???) - * - * @param vm virtual machine instance - * @param name - * @param islocal - * @return (???) - */ -BERRY_API int be_loadmode(bvm *vm, const char *name, bbool islocal); - -/** - * @fn int be_loadlib(bvm*, const char*) - * @note code load API - * @brief (???) - * - * @param vm virtual machine instance - * @param path - * @return (???) - */ -BERRY_API int be_loadlib(bvm *vm, const char *path); - -/** - * @fn int be_savecode(bvm*, const char*) - * @note code load API - * @brief (???) - * - * @param vm virtual machine instance - * @param name - * @return (???) - */ -BERRY_API int be_savecode(bvm *vm, const char *name); - -/** - * @fn void be_module_path(bvm*) - * @note module path list API - * @brief (???) - * - * @param vm virtual machine instance - */ -BERRY_API void be_module_path(bvm *vm); - -/** - * @fn void be_module_path_set(bvm*, const char*) - * @note module path list API - * @brief (???) - * - * @param vm virtual machine instance - * @param path - */ -BERRY_API void be_module_path_set(bvm *vm, const char *path); - -/** - * @fn void* be_pushbytes(bvm *vm, const void *buf, size_t len) - * @note bytes operation - * @brief Push a bytes() buffer - * - * @param vm virtual machine instance - * @param buf starting at position - * @param len size - */ -BERRY_API void* be_pushbytes(bvm *vm, const void *buf, size_t len); - -/** - * @fn const void* be_tobytes(bvm *vm, int index, size_t *len) - * @note bytes operation - * @brief return virtual stack as a bytes buffer - * - * Get the value of the index position of index from the virtual stack and return it as a bytes buffer. - * The pointer of the buffer is returned, and the size is stored in *len (unless len is NULL). - * This function works only for instances of the bytes class, or returns NULL. - * - * @param vm virtual machine instance - * @param index index from the virtual stac - * @param len size - */ -BERRY_API const void* be_tobytes(bvm *vm, int index, size_t *len); - -/** - * @fn void be_sethook(bvm*, const char*) - * @note debug API - * @brief (???) - * - * @param vm virtual machine instance - * @param mask - */ -BERRY_API void be_sethook(bvm *vm, const char *mask); - -/** - * @fn void be_setntvhook(bvm*, bntvhook, void*, int) - * @note debug API - * @brief (???) - * - * @param vm virtual machine instance - * @param hook - * @param data - * @param mask - */ -BERRY_API void be_setntvhook(bvm *vm, bntvhook hook, void *data, int mask); - -/** - * @fn void be_writebuffer(const char*, size_t) - * @note basic character IO API - * @brief implement on berry_port.c - * - * Output a piece of data to the standard output device, the parameter - * `buffer` is the first address of the output data block, and `length` is - * the length of the output data block. This function outputs to the - * `stdout` file by default. Inside the interpreter, this function is - * usually used as a character stream output, not a binary stream. - * - * @param buffer - * @param length - */ -BERRY_API void be_writebuffer(const char *buffer, size_t length); - -/** - * @fn char* be_readstring(char *buffer, size_t size) - * @note basic character IO API - * @brief implement on berry_port.c - * - * Input a piece of data from the standard input device, and read at most - * one row of data each time this function is called. The parameter - * `buffer` is the data buffer passed in by the caller, and the capacity of - * the buffer is `size`. This function will stop reading and return when - * the buffer capacity is used up, otherwise it will return when a newline - * character or end of file character is read. If the function executes - * successfully, it will directly use the `buffer` parameter as the return - * value, otherwise it will return `NULL`. - * - * This function will add the read line breaks to the read data, and each - * time the `be_readstring` function is called, it will continue to read - * from the current position. This function is only called in the - * implementation of the native function `input`, and the `be_readstring` - * function may not be implemented when it is not necessary. - * - * @param buffer - * @param size - * @return (???) - */ -BERRY_API char* be_readstring(char *buffer, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/libesp32/Berry/src/berry_conf.h b/lib/libesp32/Berry/src/berry_conf.h deleted file mode 100644 index ff5a40419e99..000000000000 --- a/lib/libesp32/Berry/src/berry_conf.h +++ /dev/null @@ -1 +0,0 @@ -#include "../default/berry_conf.h" diff --git a/lib/libesp32/Berry/testall.be b/lib/libesp32/Berry/testall.be deleted file mode 100755 index 57414dbc5bb1..000000000000 --- a/lib/libesp32/Berry/testall.be +++ /dev/null @@ -1,44 +0,0 @@ -#! ./berry -import os - -os.system('lcov', '-q -c -i -d . -o init.info') - -var exec = './berry' -var path = 'tests' -var testcases = os.listdir(path) -var total = 0, failed = 0 - -for i : testcases - if os.path.splitext(i)[1] == '.be' - print('\033[0;36mrun testcase: ' + i + '\033[0m') - var ret = os.system(exec, os.path.join(path, i)) - if ret != 0 - print('\033[0;31mreturn code:', ret, '\033[0m') - failed += 1 - end - total += 1 - end -end - -print('\033[0;32mtest results: ' + - str(total) + ' total, ' + str(failed) + ' failed' + - (failed ? '' : ' (all tests passed)') + - '.\033[0m') - -if failed != 0 - os.exit(-1) -end - -var cmds = [ - 'lcov -q -c -d ./ -o cover.info', - 'lcov -q -a init.info -a cover.info -o total.info', - 'lcov --remove total.info */usr/include/* -o final.info', - 'genhtml -q -o test_report --legend --title "lcov" --prefix=./ final.info', - 'rm -f init.info cover.info total.info final.info' -] - -for cmd : cmds - if os.system(cmd) - os.exit(-1) - end -end diff --git a/lib/libesp32/Berry/tests/assignment.be b/lib/libesp32/Berry/tests/assignment.be deleted file mode 100644 index 71bb81ebf0a6..000000000000 --- a/lib/libesp32/Berry/tests/assignment.be +++ /dev/null @@ -1,34 +0,0 @@ -class Test - var a -end - -# continuous assignment of global suffix expressions -o = Test() -o.a = 100 -assert(o.a == 100) -o.a += 10 -assert(o.a == 110) - -p = Test() -p.a = Test() -p.a.a = 50 -assert(p.a.a == 50) -p.a.a += 10 -assert(p.a.a == 60) - -# continuous assignment of local suffix expressions -def test_func() - var o = Test() - o.a = 100 - assert(o.a == 100) - o.a += 10 - assert(o.a == 110) - - var p = Test() - p.a = Test() - p.a.a = 50 - assert(p.a.a == 50) - p.a.a += 10 - assert(p.a.a == 60) -end -test_func() diff --git a/lib/libesp32/Berry/tests/bool.be b/lib/libesp32/Berry/tests/bool.be deleted file mode 100644 index 2b6bf74746cd..000000000000 --- a/lib/libesp32/Berry/tests/bool.be +++ /dev/null @@ -1,53 +0,0 @@ -# test cases for boolean expressions - -assert(1 != false && 1 != true) -assert(0 != false && 0 != true) -assert(!!1 == true) -assert(!!0 == false) - -a = true -b = false -assert(!!list == true) -assert(a && b == false) -assert(!(a && b)) -def test(a, b) - while !(a && b) - assert(false) - end -end -test(true, true) - -# bug in unary -def f(i) - var j = !i # bug if i is erroneously modified - return i -end -assert(f(1) == 1) - -#- addind bool() function -# -assert(bool() == false) -assert(bool(0) == false) -assert(bool(0.0) == false) -assert(bool(false) == false) -assert(bool(nil) == false) - -assert(bool(-1) == true) -assert(bool(3.5) == true) -assert(bool('') == false) # changed behavior -assert(bool('a') == true) -assert(bool(list) == true) -assert(bool(list()) == false) # changed behavior -assert(bool([]) == false) # changed behavior -assert(bool([0]) == true) -assert(bool(map()) == false) # changed behavior -assert(bool({}) == false) # changed behavior -assert(bool({false:false}) == true) -assert(bool({nil:nil}) == false)# changed behavior - `nil` key is ignored so the map is empty - -import introspect -assert(bool(introspect.toptr(0x1000)) == true) -assert(bool(introspect.toptr(0)) == false) - -# reproduce bug https://github.com/berry-lang/berry/issues/372 -def f() var a = false var b = true || a return a end -assert(f() == false) diff --git a/lib/libesp32/Berry/tests/bytes.be b/lib/libesp32/Berry/tests/bytes.be deleted file mode 100644 index 1f58118e7780..000000000000 --- a/lib/libesp32/Berry/tests/bytes.be +++ /dev/null @@ -1,327 +0,0 @@ -def assert_error(f, error_type) - try - f() - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == error_type) - end -end - -#- basic initialization -# -b=bytes() -assert(str(b) == "bytes('')") -b=bytes("") -assert(str(b) == "bytes('')") -b=bytes(0) -assert(str(b) == "bytes('')") -b=bytes(1) -assert(str(b) == "bytes('')") -b=bytes(-1) -assert(str(b) == "bytes(\'00\')") -assert(b.size() == 1) - -b=bytes("a") -assert(str(b) == "bytes('')") -b=bytes(3.5) -assert(str(b) == "bytes('')") -b=bytes([]) -assert(str(b) == "bytes('')") - -b=bytes("1122AAaaBBbb") -assert(str(b) == "bytes('1122AAAABBBB')") -assert(b.size() == 6) -b=bytes("112") -assert(str(b) == "bytes('11')") -b=bytes("++") -assert(str(b) == "bytes('00')") - -#- add -# -b=bytes() -b.add(0x22) -assert(str(b) == "bytes('22')") -b.add(0x12345678, 0) -assert(str(b) == "bytes('22')") -b.add(0x12345678, 1) -assert(str(b) == "bytes('2278')") -b.add(0x12345678, 2) -assert(str(b) == "bytes('22787856')") -b.add(0x12345678, 4) -assert(str(b) == "bytes('2278785678563412')") -b.add(0x12345678, -1) #- big endian -# -assert(str(b) == "bytes('227878567856341278')") -b.add(0x12345678, -2) -assert(str(b) == "bytes('2278785678563412785678')") -b.add(0x12345678, -4) -assert(str(b) == "bytes('227878567856341278567812345678')") - -#- get -# -b=bytes("000102030405") -assert(b.get(0) == 0) -assert(b.get(-1) == 0x05) #- last byte -# -assert(b.get(6) == 0) -assert(b.get(1) == 1) -assert(b.get(5) == 5) -assert(b.get(-1000) == 0) # out of range, default to zero -assert(b.get(1000) == 0) # out of range, default to zero - -assert(b.get(1,1) == 0x01) -assert(b.get(1,2) == 0x0201) -assert(b.get(1,4) == 0x04030201) -assert(b.get(1,-1) == 0x01) -assert(b.get(1,-2) == 0x0102) #- big endian -# -assert(b.get(1,-4) == 0x01020304) -assert(b.get(1,0) == 0) # size zero is invalid, returns zero -assert(b.get(-1000,1) == 0) # out of range, default to zero -assert(b.get(1000,1) == 0) # out of range, default to zero - -#- resize -# -assert(bytes().size() == 0) -b=bytes("112233") -b.resize(2) -assert(str(b) == "bytes('1122')") -assert(b.size() == 2) -b.resize(4) -assert(str(b) == "bytes('11220000')") -assert(b.size() == 4) -b.resize(20) -assert(str(b) == "bytes('1122000000000000000000000000000000000000')") -assert(b.size() == 20) -b.resize(0) -assert(str(b) == "bytes('')") -assert(b.size() == 0) -b=bytes("112233") -b.resize(-5) # resize negative is equivalent to resize(0) -assert(str(b) == "bytes('')") -assert(b.size() == 0) - -#- clear -# -b=bytes("aabb") -b.clear() -assert(str(b) == "bytes('')") - -#- == != -# -assert(bytes() == bytes()) -assert(bytes("11") == bytes("11")) -assert(bytes("11") == bytes()..0x11) -assert(! (bytes("11") == bytes(0x12)) ) -assert(! (bytes("11") == 0x11) ) -assert(! (bytes("11") != bytes("11")) ) -assert(bytes("11") != bytes("1122")) -assert(bytes("11") != bytes("12")) -assert(bytes("11") != bytes()) - -#- + -# -b1 = bytes("1122") -b2 = bytes("334455") -b = b1 + b2 -assert(str(b1) == "bytes('1122')") -assert(str(b2) == "bytes('334455')") -assert(str(b) == "bytes('1122334455')") -b = b2 + b1 -assert(str(b) == "bytes('3344551122')") - -#- + for string -# -b1 = bytes("AA") -b = b1 + '' -assert(str(b) == "bytes('AA')") -b = b1 + '01' -assert(str(b) == "bytes('AA3031')") - -#- .. and append as synonyms -# -b1 = bytes("1122") -b2 = bytes("334455") -b = b1..b2 -assert(str(b1) == "bytes('1122334455')") -assert(str(b2) == "bytes('334455')") -assert(str(b) == "bytes('1122334455')") -# -b1 = bytes("1122") -b2 = bytes("334455") -b = b1.append(b2) -assert(str(b1) == "bytes('1122334455')") -assert(str(b2) == "bytes('334455')") -assert(str(b) == "bytes('1122334455')") - -#- .. with string -# -b1 = bytes("AA") -b1 .. '' -assert(str(b1) == "bytes('AA')") -b1 .. '01' -assert(str(b1) == "bytes('AA3031')") -# -b1 = bytes("AA") -b1.append('') -assert(str(b1) == "bytes('AA')") -b1.append('01') -assert(str(b1) == "bytes('AA3031')") - -#- item -# -b = bytes("334455") -assert(b[0] == 0x33) -assert(b[1] == 0x44) -assert(b[2] == 0x55) -assert(b[-1] == 0x55) -assert(b[-2] == 0x44) -assert(b[-3] == 0x33) -# out of range raises "index_error" exceptions -assert_error(def () return b[-4] end, 'index_error') -assert_error(def () return b[4] end, 'index_error') - -#- item range -# -b = bytes("00112233445566778899AABBCCDDEEFF") -assert(str(b[1..1]) =="bytes('11')") -assert(str(b[-1..1]) =="bytes('')") -assert(str(b[0..40]) =="bytes('00112233445566778899AABBCCDDEEFF')") -assert(str(b[1..0]) =="bytes('')") - -#- copy -# -b=bytes("112233") -b2=b.copy() -assert(str(b) =="bytes('112233')") -assert(str(b2) =="bytes('112233')") -b2.clear() -assert(str(b) =="bytes('112233')") -assert(str(b2) =="bytes('')") - -#- setitem -# -b=bytes("112233") -assert(str(b) =="bytes('112233')") -b[1]=0xAA -assert(str(b) =="bytes('11AA33')") -b[0]=0xBB -assert(str(b) =="bytes('BBAA33')") -b[2]=-1 -assert(str(b) =="bytes('BBAAFF')") -# negative indices, counting from end -b[-1]=0xFE -assert(str(b) =="bytes('BBAAFE')") -b[-3]=0xBC -assert(str(b) =="bytes('BCAAFE')") -# out of range raises "index_error" exceptions -assert_error(def () b[-4]=0x11 end, 'index_error') -assert_error(def () b[4]=0x11 end, 'index_error') - -#- resize -# -b=bytes() -b.resize(20) -assert(str(b) =="bytes('0000000000000000000000000000000000000000')") -b2=b.copy() -assert(str(b2) =="bytes('0000000000000000000000000000000000000000')") - -#- asstring -# -b=bytes() -assert(b.asstring() == '') -b=bytes("334455") -assert(b.asstring() == '3DU') -b=bytes("33456502") -assert(b.asstring() == '3Ee\x02') - -#- fromstring -# -b=bytes() -b.fromstring("Aa0") -assert(str(b) =="bytes('416130')") -b=bytes() -b.fromstring("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") -assert(b.tostring(0) =="bytes('4C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742C2073656420646F20656975736D6F642074656D706F7220696E6369646964756E74207574206C61626F726520657420646F6C6F7265206D61676E6120616C697175612E')") -assert(size(bytes('4C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742C2073656420646F20656975736D6F642074656D706F7220696E6369646964756E74207574206C61626F726520657420646F6C6F7265206D61676E6120616C697175612E')) == 123) - -#- negative index -# -b=bytes("112233") -assert(b[0] == 0x11) -assert(b[-1] == 0x33) #- last element -# -assert(b[-3] == 0x11) - -#- ranges with negative indices -# -b = bytes("00112233445566778899AABBCCDDEEFF") -assert(b[0..-1] == b) -assert(b[1..-2] == bytes("112233445566778899AABBCCDDEE")) -assert(b[5..10] == bytes("5566778899AA")) -assert(b[-10..-5] == bytes("66778899AABB")) -assert(b[5..-10] == bytes("5566")) -assert(b[7..-12] == bytes()) - -#- float -# -b = bytes("00000000") -b.setfloat(0, 0.33) -assert(b == bytes('C3F5A83E')) -b = bytes("0000C03F") -assert(b.getfloat(0) == 1.5) -b.addfloat(0.33) -assert(b == bytes("0000C03FC3F5A83E")) -b.addfloat(0.33, true) #- Big Endian -# -assert(b == bytes("0000C03FC3F5A83E3EA8F5C3")) -b = bytes("") -b.addfloat(42) #- add integer -# -assert(b == bytes("00002842")) - -#- fromhex -# -b = bytes("112233") -b.fromhex("FFFEAABBCC") -assert(b == bytes("FFFEAABBCC")) -b.fromhex("") -assert(b == bytes()) - -#- tohex -# -b = bytes("FFFEAABBCC") -assert(b.tohex() == "FFFEAABBCC") -assert(bytes().tohex() == "") - -# assign buffer to bytes -var a0 = bytes("112233445566778899") -b = bytes("aabbccddeeff") - -a = a0.copy() -a.setbytes(0, b) # assign from start -assert(a == bytes('AABBCCDDEEFF778899')) -a = a0.copy() -a.setbytes(0, b, 0, 0) # zero len -assert(a == a0) -a = a0.copy() -a.setbytes(100, b) # index out of range -assert(a == a0) -a = a0.copy() -a.setbytes(6, b) # entire buffer not fitting -assert(a == bytes('112233445566AABBCC')) -a = a0.copy() -a.setbytes(6, b, 2, 2) -assert(a == bytes('112233445566CCDD99')) -a = b.copy() -a.setbytes(0, a0) -assert(a == bytes('112233445566')) - -# reverse -assert(bytes().reverse() == bytes()) -assert(bytes("AA").reverse() == bytes("AA")) -assert(bytes("1122334455").reverse() == bytes("5544332211")) -assert(bytes("11223344").reverse() == bytes("44332211")) - -assert(bytes("0011223344").reverse(1) == bytes("0044332211")) -assert(bytes("0011223344").reverse(3) == bytes("0011224433")) -assert(bytes("0011223344").reverse(4) == bytes("0011223344")) -assert(bytes("0011223344").reverse(5) == bytes("0011223344")) -assert(bytes("0011223344").reverse(15) == bytes("0011223344")) -assert(bytes("0011223344").reverse(-2) == bytes("0011224433")) # reverse starting 2 from end - -assert(bytes("0011223344").reverse(1,3) == bytes("0033221144")) -assert(bytes("0011223344").reverse(1,0) == bytes("0011223344")) -assert(bytes("0011223344").reverse(2,2) == bytes("0011332244")) -assert(bytes("0011223344").reverse(0,2) == bytes("1100223344")) -assert(bytes("0011223344").reverse(nil,2) == bytes("1100223344")) -assert(bytes("0011223344").reverse(1, nil) == bytes("0044332211")) - -assert(bytes("0011223344").reverse(nil, nil, 2) == bytes("2233001144")) -assert(bytes("001122334455").reverse(nil, nil, 3) == bytes("334455001122")) - -# tobool returns `true` is bytes() is not null, `false` if empty -assert(bool(bytes()) == false) -assert(bytes().tobool() == false) -assert(!bytes()) - -assert(bool(bytes("00")) == true) -assert(bytes("01").tobool() == true) -assert(bytes("02")) - -# retrieving 3-bytes little/big endian -a = bytes("01020304") -assert(a.get(1, 3) == 0x040302) -assert(a.get(1, -3) == 0x020304) diff --git a/lib/libesp32/Berry/tests/bytes_b64.be b/lib/libesp32/Berry/tests/bytes_b64.be deleted file mode 100644 index a7f57850e0e4..000000000000 --- a/lib/libesp32/Berry/tests/bytes_b64.be +++ /dev/null @@ -1,15 +0,0 @@ -#- base64 encode -# -b=bytes() -assert(b.tob64() == '') -b=bytes('00') -assert(b.tob64() == 'AA==') -b=bytes('1122334455') -assert(b.tob64() == 'ESIzRFU=') - -#- base64 decode -# -b=bytes().fromb64('') -assert(str(b) == str(bytes(''))) -b=bytes().fromb64('AA==') -assert(str(b) == str(bytes('00'))) -b=bytes().fromb64('ESIzRFU=') -assert(str(b) == str(bytes('1122334455'))) diff --git a/lib/libesp32/Berry/tests/bytes_fixed.be b/lib/libesp32/Berry/tests/bytes_fixed.be deleted file mode 100644 index 1f3e5532baad..000000000000 --- a/lib/libesp32/Berry/tests/bytes_fixed.be +++ /dev/null @@ -1,68 +0,0 @@ -#- test for bytes with fixed sizes -# -def assert_attribute_error(f) - try - f() - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == 'attribute_error') - end -end - -#- simple initialization -# -b=bytes(-1) -assert(str(b) == "bytes('00')") -b=bytes(-5) -assert(str(b) == "bytes('0000000000')") - -#- initialization with hex -# -b=bytes("11", -1) -assert(str(b) == "bytes('11')") -b=bytes("11", -5) -assert(str(b) == "bytes('1100000000')") -b=bytes("11223344", -4) -assert(str(b) == "bytes('11223344')") -assert(str(bytes(-3).fromb64('RFVm')) == "bytes('445566')") - -#- check that get and set still works -# -b=bytes("11223344",-4) -assert(b.get(0,2) == 0x2211) -b.set(0,0x5566,2) -assert(b.get(0,2) == 0x5566) -assert(b[0] == 0x66) -b[0]=12 -assert(b[0] == 12) - -#- resize -# -b=bytes("11223344",-4) -assert(b.resize(4) == bytes('11223344')) - -#- check that changing size raises an exception -# -b=bytes("112233", -3) -assert_attribute_error(/-> b.add(1)) -assert_attribute_error(/-> b.add(2,2)) -assert_attribute_error(/-> b.resize(4)) -assert_attribute_error(/-> b.fromstring("aaaaa")) -assert_attribute_error(/-> b.fromb64('RFVmdw==')) -assert_attribute_error(/-> b.clear()) -assert_attribute_error(/-> b.bytes()) - -#- add -# -b=bytes("112233", -3) -assert(b+b == bytes("112233112233")) - -#- bytes mapped -# -b1=bytes("112233445566") -ptr=b1._buffer() -b2=bytes(ptr, -4) -assert(b2 == bytes("11223344")) -b2=bytes(ptr, 4) -assert(b2 == bytes("11223344")) -b2=bytes(ptr, 6) -assert(b2 == bytes("112233445566")) -assert(b1 == b2) - -b2.set(0,0xAABB,2) -assert(b2 == bytes("BBAA33445566")) -assert(b1 == bytes("BBAA33445566")) -assert(b1 == b2) -assert(b1.ismapped() == false) \ No newline at end of file diff --git a/lib/libesp32/Berry/tests/checkspace.be b/lib/libesp32/Berry/tests/checkspace.be deleted file mode 100644 index 8af1a71d74c5..000000000000 --- a/lib/libesp32/Berry/tests/checkspace.be +++ /dev/null @@ -1,35 +0,0 @@ -import os - -def strfind(st, char) - var len = size(st) - for i : 0 .. len - 1 - if st[i] == char - return true - end - end - return false -end - -def checkfile(path) - var subname = os.path.splitext(path)[1] - if (subname == '.c' || subname == '.h' || - subname == '.cpp' || subname == '.be' || subname == '.json') - var f = open(path) - assert(!strfind(f.read(), '\t'), 'file \'' + path + '\' has tab character') - f.close() - end -end - -def findpath(path) - var ls = os.listdir(path) - for name : ls - var fullname = os.path.join(path, name) - if os.path.isfile(fullname) - checkfile(fullname) - elif fullname != '.' && fullname != '..' - findpath(fullname) - end - end -end - -findpath('.') diff --git a/lib/libesp32/Berry/tests/class.be b/lib/libesp32/Berry/tests/class.be deleted file mode 100644 index 06d78ee5dd16..000000000000 --- a/lib/libesp32/Berry/tests/class.be +++ /dev/null @@ -1,60 +0,0 @@ -class Test - var maximum - def init(maximum) - self.maximum = maximum - end - def iter() # method closure upvalues test - var i = -1, maximum = self.maximum - return def () - i += 1 - if i > maximum - raise 'stop_iteration' - end - return i - end - end -end - -var sum = 0 -for i : Test(10) - sum += i -end -assert(sum == 55, 'iteraion sum is ' + str(sum) + ' (expected 55).') - -#- test case for class instanciated from module member #103 -# - -m = module() -g_i = 0 #- detect side effect from init() -# -class C def init() g_i += 1 end end -m.C = C - -#- normal invocation -# -assert(type(C()) == 'instance') -assert(g_i == 1) - -#- invoke from module member -# -assert(type(m.C()) == 'instance') -assert(g_i == 2) - -class C2 var C1 def init(c) self.C1 = c end end -m.C2 = C2 -c2 = m.C2(m.C) - -assert(c2.C1 == C) - -c3 = m.C2(m.C()) -assert(type(c3.C1) == 'instance') -assert(classname(c3.C1) == 'C') - -#- an instance member can be a class and called directly -# -class Test_class - var c - def init() - self.c = map - end -end -c4 = Test_class() -assert(type(c4.c) == 'class') -c5 = c4.c() -assert(type(c5) == 'instance') -assert(classname(c5) == 'map') diff --git a/lib/libesp32/Berry/tests/class_const.be b/lib/libesp32/Berry/tests/class_const.be deleted file mode 100644 index 950ce8b4bb0d..000000000000 --- a/lib/libesp32/Berry/tests/class_const.be +++ /dev/null @@ -1,122 +0,0 @@ -def assert_attribute_error(f) - try - f() - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == 'attribute_error') - end -end - -class A - static var a - def init() self.b = 2 end - def f() end - var b - static var c, s, r -end - -assert(A.a == nil) -assert(A.c == nil) -assert(A.s == nil) -assert_attribute_error(/-> A.b) -assert_attribute_error(/-> A.d) - -a = A() -assert(a.b == 2) -assert(a.a == nil) -assert(a.c == nil) - -A.a = 1 -A.c = 3 -A.s = "foo" -A.r = 3.5 -assert(a.a == 1) -assert(a.c == 3) -assert(A.a == 1) -assert(A.c == 3) -import gc gc.collect() -assert(A.s == "foo") -assert(a.s == "foo") -assert(A.r == 3.5) -assert(a.r == 3.5) - -#- test valid or invalid methods and members -# - -def assert_attribute_error(c) - try - compile(c)() - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == 'attribute_error') - end -end - -class A - var a, g - static h - def init() self.a = 1 end - def f(x, y) return type(self) end -end -a=A() -a.g = def (x, y) return type(x) end -A.h = def (x, y) return type(x) end - -assert(type(a.g) == 'function') -assert(type(a.h) == 'function') - -assert(a.g(1) == 'int') -assert(a.h(1) == 'int') -assert(A.h(1) == 'int') - - -class A - var a - static def g(x, y) return [x,y] end - static h = def (x, y) return [x,y] end - def init() self.a = 1 end - def f(x, y) return type(self) end -end -a=A() -assert(type(a.g) == 'function') -assert(type(a.h) == 'function') -assert(type(A.g) == 'function') -assert(type(A.h) == 'function') -assert(a.g(1,2) == [1,2]) -assert(a.h(1,2) == [1,2]) -assert(A.g(1,2) == [1,2]) -assert(A.h(1,2) == [1,2]) -a.a = def (x,y) return [x,y] end -assert(a.a(1,2) == [1,2]) - - -#- test static initializers -# -class A - static a = 1, b, c = 3.5, d = 42, e = "foo", f = [1], g = {} - var aa,ab -end - -assert(A.a == 1) -assert(A.b == nil) -assert(A.c == 3.5) -assert(A.d == 42) -assert(A.e == "foo") -assert(A.f == [1]) - -a = A() -assert(a.a == 1) -assert(a.b == nil) -assert(a.c == 3.5) -assert(a.d == 42) -assert(a.e == "foo") -assert(a.f == [1]) -assert(a.g == A.g) -assert(a.aa == nil) -assert(a.ab == nil) - -#- used to fail for subclasses -# -class A static a=1 end -class B:A static a=A def f() end static b=1 static c=A end -assert(A.a == 1) -assert(B.a == A) -assert(B.b == 1) -assert(B.c == A) diff --git a/lib/libesp32/Berry/tests/closure.be b/lib/libesp32/Berry/tests/closure.be deleted file mode 100644 index 757c2a94450c..000000000000 --- a/lib/libesp32/Berry/tests/closure.be +++ /dev/null @@ -1,16 +0,0 @@ -#- test for issue #105 -# - -l=[] -def tick() - var start=100 - for i : 1..3 - l.push(def () return [i, start] end) - end -end -tick() -assert(l[0]() == [1, 100]) -assert(l[1]() == [2, 100]) -assert(l[2]() == [3, 100]) - -# the following failed to compile #344 -def test() var nv = 1 var f = def() nv += 2*1 print(nv) end end diff --git a/lib/libesp32/Berry/tests/compiler.be b/lib/libesp32/Berry/tests/compiler.be deleted file mode 100644 index a2b25640ef56..000000000000 --- a/lib/libesp32/Berry/tests/compiler.be +++ /dev/null @@ -1,80 +0,0 @@ -#- test for issue #117 -# - -class A var a end -a=A() -a.a = ["foo", "bar"] - -s = nil -def fs(m) s = m end - -class B - var b, i - def nok() - fs(self.b.a[self.i]) # wrong behavior - end - def ok() - var i = self.i - fs(self.b.a[i]) # works correctly - end -end -b=B() -b.i=0 -b.b=a - -b.nok() -assert(s == "foo") - -b.ok() -assert(s == "foo") - -# detect a wrong compilation when accessing index -# Berry compilation problem: -# -# ```berry -# def f(self) print(self.a[128]) end -# ``` -# -# Compilation assigns unwanted registers: -# ``` -# 0x60040001, // 0000 GETGBL R1 G1 -# 0x540A007F, // 0001 LDINT R2 128 -# 0x880C0100, // 0002 GETMBR R3 R0 K0 -# 0x94080602, // 0003 GETIDX R2 R3 R2 -# 0x5C100400, // 0004 MOVE R4 R2 <- PROBLEM -# 0x7C040200, // 0005 CALL R1 1 -# 0x80000000, // 0006 RET 0 -# ``` -# -# With the fix, the integer is retrieved in second place, and erroneous register is not allocated: -# ``` -# 0x60040001, // 0000 GETGBL R1 G1 -# 0x88080100, // 0001 GETMBR R2 R0 K0 -# 0x540E007F, // 0002 LDINT R3 128 -# 0x94080403, // 0003 GETIDX R2 R2 R3 -# 0x7C040200, // 0004 CALL R1 1 -# 0x80000000, // 0005 RET 0 -# ``` -def f(a,b) return b end -l = [1,2,3,4] -assert(f(l[-1],l[-2]) == 3) - -# Compilation problem: -# def test() -# var line = '1234567890' -# line = line[3..7] -# # print(line) -# for n : 1..2 end -# end -# test() - -# BRY: Exception> 'attribute_error' - the 'range' object has no method '()' -# stack traceback: -# :5: in function `test` -# :7: in function `main` -def test() - var line = '1234567890' - line = line[3..7] -# print(line) - for n : 1..2 end -end -test() diff --git a/lib/libesp32/Berry/tests/compound.be b/lib/libesp32/Berry/tests/compound.be deleted file mode 100644 index b75c2dc523d3..000000000000 --- a/lib/libesp32/Berry/tests/compound.be +++ /dev/null @@ -1,28 +0,0 @@ -# test bug in compound statements - -a = 0 -assert(a == 0) -a += 1 -assert(a == 1) -a += 10/2 -assert(a == 6) - -class A var a def init() self.a = 1 end def f(x) self.a+=x/2 end def g(x) self.a = self.a + x/2 end end - -a = A() -assert(a.a == 1) -a.f(10) -assert(a.a == 6) -b=A() -assert(b.a == 1) -b.g(10) -assert(b.a == 6) - -# bug in compound assignments -class A var a,b end -c=A() -c.a = {"x": 1, "y": 2} -c.b = "x" -assert(c.a[c.b] == 1) -c.a[c.b] += 2 # this is where the bug happens -assert(c.a[c.b] == 3) diff --git a/lib/libesp32/Berry/tests/cond_expr.be b/lib/libesp32/Berry/tests/cond_expr.be deleted file mode 100644 index dc70fd306788..000000000000 --- a/lib/libesp32/Berry/tests/cond_expr.be +++ /dev/null @@ -1,10 +0,0 @@ -assert("" != 0 ? true : false) -assert(false || !(true ? false : true) && true) -var t1 = 8, t2 = false -if t1 ? 7 + t1 : t2 - var a = 'good' - assert((a == 'good' ? a + '!' : a) == 'good!') - assert((a == 'good?' ? a + '!' : a) != 'good!') -else - assert('condition expression test failed') -end diff --git a/lib/libesp32/Berry/tests/debug.be b/lib/libesp32/Berry/tests/debug.be deleted file mode 100644 index 88b559d8108a..000000000000 --- a/lib/libesp32/Berry/tests/debug.be +++ /dev/null @@ -1,29 +0,0 @@ -import debug - -class A end -debug.attrdump(A) #- should not crash -# - -# debug.caller() -def caller_name_chain() - import debug - import introspect - var i = 1 - var ret = [] - var caller = debug.caller(i) - while caller - ret.push(introspect.name(caller)) - i += 1 - caller = debug.caller(i) - end - return ret -end -var chain = caller_name_chain() -assert(chain[0] == 'caller_name_chain') - -def guess_my_name__() - return caller_name_chain() -end -chain = guess_my_name__() -print(chain) -assert(chain[0] == 'caller_name_chain') -assert(chain[1] == 'guess_my_name__') diff --git a/lib/libesp32/Berry/tests/exceptions.be b/lib/libesp32/Berry/tests/exceptions.be deleted file mode 100644 index dc2ad54e4b71..000000000000 --- a/lib/libesp32/Berry/tests/exceptions.be +++ /dev/null @@ -1,7 +0,0 @@ - -try - for k: 0..1 assert({'a':1}.contains('b'), 'failure') end -except .. as e,m - assert(e == "assert_failed") - assert(m == "failure") -end diff --git a/lib/libesp32/Berry/tests/for.be b/lib/libesp32/Berry/tests/for.be deleted file mode 100644 index ec4a910cd0af..000000000000 --- a/lib/libesp32/Berry/tests/for.be +++ /dev/null @@ -1,44 +0,0 @@ -var global - -global = 0 -for i : 0 .. 10 - global += i -end -assert(global == 55) - -global = 0 -for i : 0 .. 20 - if i > 10 - break - end - global += i -end -assert(global == 55) - -global = 0 -for i : 0 .. 20 - if i > 10 - continue - end - global += i -end -assert(global == 55) - -assert(def () - for i : 0 .. 20 - if i > 10 - return i - end - end - end() == 11) - -# test for "stop_iteration" exception as recurrence -def for_rec(depth) - for i : 0 .. 10 - if i == 4 && depth < 200 - for_rec(depth + 1) - end - end -end - -for_rec(0) diff --git a/lib/libesp32/Berry/tests/function.be b/lib/libesp32/Berry/tests/function.be deleted file mode 100644 index 81310408bf42..000000000000 --- a/lib/libesp32/Berry/tests/function.be +++ /dev/null @@ -1,12 +0,0 @@ -# CLOSE opcode test -var gbl -def func1() - var a = 'func1_a' - def func2() - return a - end - gbl = func2 - return 400000 + 500 -end -assert(func1() == 400500) -assert(gbl() == 'func1_a') diff --git a/lib/libesp32/Berry/tests/global.be b/lib/libesp32/Berry/tests/global.be deleted file mode 100644 index 66135c4e16a7..000000000000 --- a/lib/libesp32/Berry/tests/global.be +++ /dev/null @@ -1,43 +0,0 @@ -#- test module global -# - -def assert_syntax_error(code) - try - var f = compile(code) - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == 'syntax_error') - end -end -def findinlist(l, e) - for i: 0..size(l)-1 - if l[i] == e return i end - end - return nil -end - -#- set the scene -# -global_a = 1 -global_b = "bb" -assert(global_a == 1) -assert(global_b == "bb") - -assert_syntax_error("c") #- compilation fails because c does not exist -# - -import global - -assert(global.global_a == 1) -assert(global.global_b == "bb") - -global.global_c = 3 -#- now compilation against 'c' global -# -f = compile("return global_c") -assert(f() == 3) - -#- check that access to non-existent global returns nil (new behavior) -# -assert(global.d == nil) - -#- check the glbal list -# -assert(findinlist(global(), 'global_a') != nil) -assert(findinlist(global(), 'global_b') != nil) -assert(findinlist(global(), 'global_c') != nil) -assert(findinlist(global(), 'global_d') == nil) \ No newline at end of file diff --git a/lib/libesp32/Berry/tests/introspect.be b/lib/libesp32/Berry/tests/introspect.be deleted file mode 100644 index 1d9c7af293cc..000000000000 --- a/lib/libesp32/Berry/tests/introspect.be +++ /dev/null @@ -1,66 +0,0 @@ -#- introspect -# -import introspect - -#- test for modules -# -m = module("m") -m.a = 1 -m.b = def () return "foo" end - -assert(introspect.members(m) == ['a', 'b']) -assert(introspect.get(m, 'a') == 1) -assert(type(introspect.get(m, 'b')) == 'function') - -introspect.set(m, 'a', 2) -assert(m.a == 2) - -#- test for instance -# -class A var a,b static c=1,d=2 def f() end end -a=A() - -assert(introspect.members(A) == ['a', 'f', 'b', 'c', 'd']) #- class members -# -assert(introspect.members(a) == ['a', 'f', 'b', 'c', 'd']) #- instance members -# - -assert(introspect.get(a, 'c') == 1) -assert(introspect.get(a, 'd') == 2) -assert(introspect.get(a, 'a') == nil) - -introspect.set(a, 'a', 3) -assert(a.a == 3) - -#- load module dynamically -# -import introspect -m = introspect.module("math") # load module `math`, assign to `m` and don't create a global variable -assert(type(m.pi) == 'real') - -#- name -# -import string -assert(introspect.name(string) == 'string') -assert(introspect.name(print) == nil) # native C function don't have a registered name -assert(introspect.name("foo") == nil) -class A def a() end static def b() end static var c end -assert(introspect.name(A) == 'A') -assert(introspect.name(A.a) == 'a') -assert(introspect.name(A.b) == 'b') -assert(introspect.name(A.c) == nil) - -# test introspect get and set -# class and instance -class A - static var a - var b -end - -a = A() -introspect.set(A, "a", 10) -assert(A.a == 10) -assert(introspect.get(A, "a") == 10) - -introspect.set(a, "b", 20) -assert(a.b == 20) -assert(introspect.get(a, "b") == 20) - -# module -m = module('m') -introspect.set(m, 'c', 30) -assert(m.c == 30) -assert(introspect.get(m, 'c') == 30) diff --git a/lib/libesp32/Berry/tests/json.be b/lib/libesp32/Berry/tests/json.be deleted file mode 100644 index 2165eda8d736..000000000000 --- a/lib/libesp32/Berry/tests/json.be +++ /dev/null @@ -1,95 +0,0 @@ -import json -import string -# load tests - -def assert_load(text, value) - var loaded_val = json.load(text) - var ok = loaded_val == value - if !ok - print(string.format('for JSON \'%s\' expected %s [%s] but got %s [%s]', text, str(value), type(value), str(loaded_val), type(loaded_val))) - end - assert(ok) -end - -def assert_load_failed(text) - assert(json.load(text) == nil) -end - -assert_load('null', nil) -assert_load('true', true) -assert_load('false', false) -assert_load('123', 123) -assert_load('12.3', 12.3) -assert_load('-0.1', -0.1) -assert_load('1e2', 1e2) -assert_load('1e+2', 1e+2) -assert_load('1e-2', 1e-2) -assert_load('1E2', 1e2) -assert_load('1E+2', 1e+2) -assert_load('1.2e7', 1.2e7) -assert_load('"abc"', 'abc') -# strings -assert_load('"\\"\\\\\\/\\b\\f\\n\\r\\t"', '\"\\/\b\f\n\r\t') -assert_load('"\\u1234\\u2345\\u04aF\\u003A"', 'ሴ⍅ү:') -assert_load_failed('"\\u3fr"'); -assert_load_failed('"\\q"'); -assert_load_failed('"123'); -# list -assert_load('[1, null]', [1, nil]) -assert_load_failed('[x]') -assert_load_failed('[1, nil]') -assert_load_failed('[1, null') -# object -var o = json.load('{"key": 1}') -assert(o['key'] == 1 && o.size() == 1) - -# parsing an empty string used to cause berry to pass a NULL to strncmp -# make sure we catch this -o = json.load('{"key": ""}') -assert(o['key'] == '' && o.size() == 1) - -assert_load_failed('{"ke: 1}') -assert_load_failed('{"key": 1x}') -assert_load_failed('{"key"}') -assert_load_failed('{"key": 1, }') -# insanely long, nested object -var text = 'null' -for i : 0 .. 200 - text = '{"nested":' + text + ', "num": 1, "bool": true, "str": "abc", "n": null, "arr": [1, 2, 3]}' -end -json.load(text) # do nothing, just check that it doesn't crash - -# dump tests - -def assert_dump(value, text, format) - assert(json.dump(value, format) == text) -end - -assert_dump(nil, 'null'); -assert_dump(true, 'true'); -assert_dump(false, 'false'); -assert_dump(1.23, '1.23'); -assert_dump('String', '"String"'); -assert_dump([1, 'x'], '[1,"x"]'); -assert_dump({1: 'x'}, '{"1":"x"}'); -assert_dump([1, 'x'], '[\n 1,\n "x"\n]', 'format'); -assert_dump({1: 'x'}, '{\n "1": "x"\n}', 'format'); -assert_dump({1: 'x', 'k': 'v'}, '{"k":"v","1":"x"}'); - -class map2 : map def init() super(self).init() end end -var m = map2() -m['key'] = 1 -assert_dump(m, '{"key":1}') - -# sweep dumping nested arrays of diffrent sizes -# this tests for any unexpanded stack conditions -for count : 10..200 - var arr = [[]] - var last_arr = arr - for i : 0..count - var pushed = [i] - last_arr.push(pushed) - last_arr = pushed - end - json.dump(arr) -end diff --git a/lib/libesp32/Berry/tests/lexer.be b/lib/libesp32/Berry/tests/lexer.be deleted file mode 100644 index db2945bc7e8e..000000000000 --- a/lib/libesp32/Berry/tests/lexer.be +++ /dev/null @@ -1,65 +0,0 @@ -import math - -def check(a, b) - assert(math.abs(a - b) < 1e-6) -end - -def test_source(src, msg) - try - compile(src) - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == 'syntax_error') - assert(m == 'string:1: ' + msg) - end -end - -#---- - this is a - mult-line comment -----# - -compile('x = 5; 0..x') -assert('\x5a' == 'Z') -assert('\132' == 'Z') -assert('\a\b\f\n\r\t\v\\\'\"\?' == '\x07\x08\x0c\x0a\x0d\x09\x0b\x5c\x27\x22\x3f') -assert(.45 == 0.45) -assert(0X10 == 16) -assert(0x10 == 16) -assert(0X1A == 26) -assert(0x1a == 26) -check(45., 45) -check(45.e-1, 4.5) -check(45.E-1, 4.5) -check(45.1e-1, 4.51) -check(45.1e2, 4510) -check(45.e2, 4500) -check(45.e+2, 4500) - -# Ensure pathologically long numbers don't crash the lexer (or cause an buffer overflow) -assert(000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 == 0.0); - - -test_source('x = 5; 0...x;', 'unexpected symbol near \'.\'') -test_source('x = 5; 0...x;', 'unexpected symbol near \'.\'') -test_source('0xg', 'invalid hexadecimal number') -test_source('"\\x5g"', 'invalid hexadecimal number') -test_source('0x5g', 'malformed number') -test_source('"\\779"', 'invalid octal number') -test_source('"\n', 'unfinished string') - -var malformed_numbers = [ - '45f', - '45.f', - '45.ef', - '45.e-f', - '45.e-1f', - '45.e-1.', - '45.5.', - '0x45.', - '0x45j' -] - -for i : malformed_numbers - test_source(i, 'malformed number') -end diff --git a/lib/libesp32/Berry/tests/lexergc.be b/lib/libesp32/Berry/tests/lexergc.be deleted file mode 100644 index 155800b95cea..000000000000 --- a/lib/libesp32/Berry/tests/lexergc.be +++ /dev/null @@ -1,12 +0,0 @@ -#- check the gc bug fixed in #110 -# -#- Berry must be compiled with `#define BE_USE_DEBUG_GC 1` -# -#- for the initial bug to happen -# - -code = "()" #- this code triggers a lexer exception -# - -try - compile(code) - assert(false) #- this should never be reached -# -except .. as e, m - assert(m == "string:1: unexpected symbol near ')'") -end \ No newline at end of file diff --git a/lib/libesp32/Berry/tests/list.be b/lib/libesp32/Berry/tests/list.be deleted file mode 100644 index a2da2ca473ee..000000000000 --- a/lib/libesp32/Berry/tests/list.be +++ /dev/null @@ -1,140 +0,0 @@ -l = [1, 2, 3, 4, 5] -assert(l[0] == 1) -assert(l[1] == 2) -assert(l[2] == 3) -assert(l[3] == 4) -assert(l[4] == 5) -assert(str(l) == '[1, 2, 3, 4, 5]') - -it = l.iter() -assert(it() == 1) -assert(it() == 2) -assert(it() == 3) -assert(it() == 4) -assert(it() == 5) - -l.insert(0, 10) -assert(l[0] == 10) -assert(l.size() == 6) -l.remove(0) -assert(l.size() == 5) -assert(l[0] == 1) -l.setitem(0, 42) -assert(l[0] == 42) -assert(l.item(2) == 3) -l.resize(10) -assert(l.size() == 10) -assert(l.tostring() == '[42, 2, 3, 4, 5, nil, nil, nil, nil, nil]') - -assert(([] == []) == true) -assert(([] != []) == false) -assert(([1] == [1]) == true) -assert(([1] != [1]) == false) -assert(([1] == [0]) == false) -assert(([1] != [0]) == true) -assert(([1, 2, 3] == [1, 2, 3]) == true) -assert(([1, 2, 3] != [1, 2, 3]) == false) -assert(([1, 2, 3] == [1, 2, 4]) == false) -assert(([1, 2, 3] != [1, 2, 4]) == true) -assert(([1, 2, ['w']] == [1, 2, ['w']]) == true) -assert(([1, 2, ['w']] != [1, 2, ['w']]) == false) -assert(([1, 2, ['w']] == [1, 2, ['z']]) == false) -assert(([1, 2, ['w']] != [1, 2, ['z']]) == true) -assert(([1, 2, ['w']] == [1, 2, []]) == false) -assert(([1, 2, ['w']] != [1, 2, []]) == true) - -var l = [0, 1, 2, 3] -assert(l[-1] == 3) -assert(l[-2] == 2) -var t = l.copy() -l.insert(-2, 4) -assert(t == [0, 1, 2, 3] && t != l) -assert(l == [0, 1, 4, 2, 3]) -l.remove(-2) -assert(l == [0, 1, 4, 3]) -assert(l.reverse() == [3, 4, 1, 0]) -assert(l + [5, 6] == [3, 4, 1, 0, 5, 6]) -l = [0] -assert(l .. '3' == [0, '3']) -l.push(1) -assert(l == [0, '3', 1]) -assert(l.concat() == '031') -l.pop() -assert(l == [0, '3']) -l.pop(0) -assert(l == ['3']) - -l1 = [0, 1] -l2 = [2, 3] -assert(l1+l2==[0, 1, 2, 3]) -assert(l1 == [0, 1]) -assert(l2 == [2, 3]) -assert(l1+[2] == [0, 1, 2]) -assert([-1]+l1 == [-1, 0, 1]) -assert(l1 == [0, 1]) - -#- find -# -#- if no argument return nil -# -assert([].find() == nil) -assert([1,2].find() == nil) -assert([1,1,nil,2].find() == nil) - -#- nil if not found -# -assert([1,2].find(3) == nil) -assert([1,2].find(true) == nil) -assert([1,2].find('foo') == nil) - -#- if found -# -assert([1,2,3,4].find(1) == 0) -assert([1,2,3,4].find(2) == 1) -assert([1,2,3,4].find(3) == 2) -assert([1,2,3,4].find(4) == 3) -assert([1,2,"foo",4].find('foo') == 2) - -#- if multiple occurrences -# -assert([1,1,2,2].find(1) == 0) -assert([1,1,2,2].find(2) == 2) - -#- look for nil -# -assert([1,1,nil,2].find(nil) == 2) - -#- sub-structure -# -assert([1,[1,nil,2],3,[3]].find(3) == 2) -assert([1,[1,nil,2],3,[3]].find([3]) == 3) -assert([1,[1,nil,2],3,[3]].find([1,nil,2]) == 1) - -#- keys() -# -assert(str(["a",'b',0].keys()) == "(0..2)") -assert(str([nil].keys()) == "(0..0)") -assert(str([].keys()) == "(0..-1)") - -#- concat with delimiter -# -assert(["foo","bar",0].concat() == "foobar0") -assert([1,2,3].concat() == "123") -assert(["foo","bar",0].concat('') == "foobar0") -assert([1,2,3].concat('') == "123") - -assert(["foo","bar",0].concat('-') == "foo-bar-0") -assert([].concat('<->') == "") -assert(["foo"].concat('<->') == "foo") -assert(["foo","bar",0].concat('<->') == "foo<->bar<->0") - -assert(["","foo","bar",0].concat('<->') == "<->foo<->bar<->0") -assert(["","",1,"bar",0].concat('<->') == "<-><->1<->bar<->0") -assert(["","",1,"bar",0].concat('') == "1bar0") - -assert([1,2,3].concat('-') == "1-2-3") -assert([1,"2",3].concat('-') == "1-2-3") - -assert(["",2,3].concat('-') == "-2-3") - -#- negative indices -# -assert([1,2,3,4][0] == 1) -assert([1,2,3,4][-1] == 4) -assert([1,2,3,4][-2] == 3) - -assert([1,2,3,4][1..10] == [2,3,4]) -assert([1,2,3,4][1..-1] == [2,3,4]) -assert([1,2,3,4][1..-2] == [2,3]) -assert([1,2,3,4][3..2] == []) -assert([1,2,3,4][2..-3] == []) \ No newline at end of file diff --git a/lib/libesp32/Berry/tests/member_indirect.be b/lib/libesp32/Berry/tests/member_indirect.be deleted file mode 100644 index 046521acdc47..000000000000 --- a/lib/libesp32/Berry/tests/member_indirect.be +++ /dev/null @@ -1,75 +0,0 @@ -#- new syntax for indirect members -# - -#- module accessor -# -s_pi = 'pi' - -import math -assert(math.('pi') == math.pi) -assert(math.(s_pi) == math.pi) - -#- module writer -# -m = module("m") - -m.('aa') = 1 -m.('a' + 'b') = 2 -s_ac = 'ac' -m.(s_ac) = 3 -assert(m.aa == 1) -assert(m.ab == 2) -assert(m.ac == 3) -assert(m.('a'+'a') == 1) - -#- class accessor -# -class A1 - static a = 1, b = 2 - static s = "foo" - def f() return 0 end -end -assert(A1.a == 1) -assert(A1.b == 2) -assert(A1.s == "foo") -assert(type(A1.f) == 'function') - -#- instance accessor -# -class A2 - var a, b - static s_a = 'a' - def init(a,b) - self.(self.('s_a')) = a - self.('b') = b - end - def f(x) - return x+1 - end - def g(a,b) - return A2(a,b) - end -end -a = A2(1,2) - -#- reading members -# -assert(a.a == 1) -assert(a.b == 2) -assert(a.(A2.s_a) == 1) -assert(a.('b') == 2) - -#- writing members -# -a.('a') = 10 -a.('bb'[0]) = 11 -assert(a.a == 10) -assert(a.b == 11) - -#- calling methods -# -assert(a.f(1) == 2) -assert(a.('f')(2) == 3) - -#- mulit-level -# -assert(a.('g')(3,4).('a') == 3) -a.('a') = a.g(3,4) -assert(a.a.b == 4) -assert(a.('a').b == 4) -assert(a.('a').('b') == 4) -assert(a.a.('b') == 4) - -a.('a').('b') += 1 -assert(a.a.b == 5) diff --git a/lib/libesp32/Berry/tests/os.be b/lib/libesp32/Berry/tests/os.be deleted file mode 100644 index 58f41c9d0ec8..000000000000 --- a/lib/libesp32/Berry/tests/os.be +++ /dev/null @@ -1,51 +0,0 @@ -import os - -# os.path.join test -assert(os.path.join('') == '') -assert(os.path.join('abc', 'de') == 'abc/de') -assert(os.path.join('abc', '/de') == '/de') -assert(os.path.join('a', 'de') == 'a/de') -assert(os.path.join('abc/', 'de') == 'abc/de') -assert(os.path.join('abc', 'de', '') == 'abc/de/') -assert(os.path.join('abc', '', '', 'de') == 'abc/de') -assert(os.path.join('abc', '/de', 'fghij') == '/de/fghij') -assert(os.path.join('abc', 'xyz', '/de', 'fghij') == '/de/fghij') - -# os.path.split test -def split(st, lst) - var res = os.path.split(st) - assert(res[0] == lst[0] && res[1] == lst[1], - 'unexpected results: ' .. res .. ', reference value: ' .. lst) -end - -split('/', ['/', '']) -split('//', ['//', '']) -split('///', ['///', '']) -split('a/', ['a', '']) -split('a//', ['a', '']) -split('a/b/c', ['a/b', 'c']) -split('a/b/', ['a/b', '']) -split('a//b//', ['a//b', '']) -split('a/../b', ['a/..', 'b']) -split('abcd////ef/////', ['abcd////ef', '']) -split('abcd////ef', ['abcd', 'ef']) - -# os.path.splitext test -def splitext(st, lst) - var res = os.path.splitext(st) - assert(res[0] == lst[0] && res[1] == lst[1], - 'unexpected results: ' .. res .. ', reference value: ' .. lst) -end - -splitext('a.b', ['a', '.b']) -splitext('a..b', ['a.', '.b']) -splitext('/a..b', ['/a.', '.b']) -splitext('/.b', ['/.b', '']) -splitext('/..b', ['/..b', '']) -splitext('..b', ['..b', '']) -splitext('...b', ['...b', '']) -splitext('.b', ['.b', '']) -splitext('ac..b', ['ac.', '.b']) -splitext('ac.b', ['ac', '.b']) -splitext('ac/.b', ['ac/.b', '']) -splitext('ac/..b', ['ac/..b', '']) diff --git a/lib/libesp32/Berry/tests/overload.be b/lib/libesp32/Berry/tests/overload.be deleted file mode 100644 index a9e72081baf5..000000000000 --- a/lib/libesp32/Berry/tests/overload.be +++ /dev/null @@ -1,14 +0,0 @@ -class test - def init() - self._a = 123 - end - def +() - return self._a - end - def ()() - return self._a - end - var _a -end - -print(test() + test()) diff --git a/lib/libesp32/Berry/tests/relop.be b/lib/libesp32/Berry/tests/relop.be deleted file mode 100644 index a9a9805f15d0..000000000000 --- a/lib/libesp32/Berry/tests/relop.be +++ /dev/null @@ -1,40 +0,0 @@ -def assert_true(status) - assert(status == true, 'assert(true) failed!') -end - -def assert_false(status) - assert(status == false, 'assert(false) failed!') -end - -assert_true(0 == 0) -assert_false(0 != 0) -assert_true(0 != 1) -assert_false(0 == 1) - - -assert_true(0.0 == 0) -assert_false(0.0 != 0) -assert_true(0.0 != 1.0) -assert_false(0.0 == 1.0) - -assert_true(nil == nil) -assert_false(nil != nil) -assert_true(true != nil) -assert_false(true == nil) -assert_true(nil != false) -assert_false(nil == false) - -assert_true(list == list) -assert_false(list == map) - -assert_true([] == []) -assert_true([true] == [true]) -assert_true([[]] == [[]]) -assert_false([[]] != [[]]) -assert_false([0] == []) -assert_false([] != []) -assert_true([] != nil) -assert_false([] == nil) - -assert_true({} != nil) -assert_false({} == nil) diff --git a/lib/libesp32/Berry/tests/string.be b/lib/libesp32/Berry/tests/string.be deleted file mode 100644 index 448ca52157ee..000000000000 --- a/lib/libesp32/Berry/tests/string.be +++ /dev/null @@ -1,215 +0,0 @@ -import string as s - -assert(s.find('012345', '23') == 2) -assert(s.find('012345', '23', 1) == 2) -assert(s.find('012345', '23', 1, 3) == -1) -assert(s.find('012345', '23', 2, 4) == 2) -assert(s.find('012345', '23', 3) == -1) - -assert(s.find('012345', '') == 0) -assert(s.find('012345', '', 0, 0) == 0) -assert(s.find('012345', '', 1) == 1) -assert(s.find('012345', '', 1, 1) == 1) -assert(s.find('012345', '', 1, 0) == -1) -assert(s.find('012345', '', 6) == 6) -assert(s.find('012345', '', 7) == -1) - -assert(s.count('012345', '') == 7) -assert(s.count('012345', '', 2) == 5) -assert(s.count('012345', '', 6) == 1) - -assert(s.count('121314', '1') == 3) -assert(s.count('121314', '1', 1) == 2) -assert(s.count('121314', '1', 2) == 2) -assert(s.count('121314', '1', 1, 2) == 0) -assert(s.count('121314', '1', 1, 3) == 1) - -assert(s.split('a b c d e f', '1') == ['a b c d e f']) -assert(s.split('a b c d e f', ' ') == ['a', 'b', 'c', 'd', 'e', 'f']) -assert(s.split('a b c d e f', ' ', 2) == ['a', 'b', 'c d e f']) -assert(s.split('a b c d e f', '') == ['a b c d e f']) - -assert(s.format("%%") == "%") -assert(s.format("%i%%", 12) == "12%") -assert(s.format("%i%%%i", 12, 13) == "12%13") -assert(s.format("%s%%", "foo") == "foo%") -assert(s.format("%.1f%%", 3.5) == "3.5%") - -s="azerty" -assert(s[1..2] == "ze") -assert(s[1..] == "zerty") -assert(s[1..-1] == "zerty") - -#- string ranges -# -s="azertyuiop" -assert(s[0] == "a") -assert(s[0..1] == "az") -assert(s[0..2] == "aze") -assert(s[0..10] == s) -assert(s[0..size(s)] == s) -assert(s[0..50] == s) #- upper limit is allowed to be out of range -# - -#- negative indices start from the end -# -s="azertyuiop" -assert(s[-1] == "p") -assert(s[-2] == "o") -assert(s[0..-2] == "azertyuio") -assert(s[-4..-2] == "uio") -assert(s[-2..-4] == "") #- if range is in wrong order, returns empty string -# -assert(s[-40..-2] == "azertyuio") #- borders are allowed to be out of range -# - -# escape -import string -assert(string.escape("A") == '"A"') -assert(string.escape("A", true) == "'A'") -assert(string.escape("\"") == '"\\""') -assert(string.escape("\"", true) == '\'"\'') - -var s ='"a\'b"\'' -assert(string.escape(s) == '"\\"a\'b\\"\'"') -assert(string.escape(s, true) == '\'"a\\\'b"\\\'\'') - -# tr -assert(string.tr("azer", "abcde", "ABCDE") == 'AzEr') -assert(string.tr("azer", "", "") == 'azer') -assert(string.tr("azer", "aaa", "ABC") == 'Azer') # only first match works -assert(string.tr("A_b", "_", " ") == 'A b') -# tr used to remove characters -assert(string.tr("qwerty", "qwe", "_") == '_rty') - -# the following should not crash -var s1 = 'A string of more than 128 bytes 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' -var s2 = string.format("%i, %s", 1, s1) - -# replace -assert(string.replace("hello", "ll", "xx") == "hexxo") -assert(string.replace("hellollo", "ll", "xx") == "hexxoxxo") -assert(string.replace("hellollo", "aa", "xx") == "hellollo") -assert(string.replace("hello", "ll", "") == "heo") -assert(string.replace("hello", "", "xx") == "hello") -assert(string.replace("hello", "", "") == "hello") - -# multi-line strings -var s = "a" "b""c" -assert(s == 'abc') - -s = 'a'"b"'''c' -assert(s == 'abc') - -s = "a" -'b' - "" - "c" -assert(s == 'abc') - -s = "a" #- b -# "b" #--# "c" -assert(s == 'abc') - -s = "a"# - # "z" - "b" # zz - "c" -assert(s == 'abc') - -# string.format with automatic conversion -import string - -assert(string.format("%i", 3) == '3') -assert(string.format("%i", "3") == '3') -assert(string.format("%i", "03") == '3') -assert(string.format("%i", nil) == '') - -class A def toint() return 42 end end -a=A() -class B end -b=B() - -assert(string.format("%i", a) == '42') -assert(string.format("%i", b) == '') - -assert(string.format("%i", nil) == '') -assert(string.format("%i", true) == '1') -assert(string.format("%i", false) == '0') - -assert(string.format("%c", a) == '*') - -assert(string.format("%f", 3.5) == '3.500000') -assert(string.format("%f", 3) == '3.000000') -assert(string.format("%.1f", 3) == '3.0') -assert(string.format("%.1f", nil) == '') -assert(string.format("%.1f", true) == '') -assert(string.format("%.1f", false) == '') -assert(string.format("%.1f", a) == '') - -assert(string.format("%s", a) == '') -assert(string.format("%s", 0) == '0') -assert(string.format("%s", nil) == 'nil') -assert(string.format("%s", true) == 'true') -assert(string.format("%s", false) == 'false') - -assert(string.format("%q", "\ntest") == '\'\\ntest\'') - -# corrupt format string should not crash the VM -string.format("%0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f", 3.5) - -# format is now synonym to string.format -assert(format == string.format) -assert(format("%.1f", 3) == '3.0') - -# f-strings -assert(f"" == '') -assert(f'' == '') -assert(f"abc\n\r\t" == 'abc\n\r\t') -assert(f'{{a}}' == '{a}') -assert(f'\\\\' == '\\\\') - -assert(f"A = {1+1}" == 'A = 2') -assert(f"A = {1+1:s}" == 'A = 2') -assert(f"A = {1+1:i}" == 'A = 2') -assert(f"A = {1+1:04i}" == 'A = 0002') - -assert(f"P = {3.1415:.2f}" == 'P = 3.14') - -var a = 'foobar{0}' -assert(f"S = {a}" == 'S = foobar{0}') -assert(f"S = {a:i}" == 'S = 0') -assert(f"{a=}" == 'a=foobar{0}') - -# startswith case sensitive -assert(string.startswith("", "") == true) -assert(string.startswith("qwerty", "qw") == true) -assert(string.startswith("qwerty", "qwerty") == true) -assert(string.startswith("qwerty", "") == true) -assert(string.startswith("qwerty", "qW") == false) -assert(string.startswith("qwerty", "QW") == false) -assert(string.startswith("qwerty", "qz") == false) -assert(string.startswith("qwerty", "qwertyw") == false) - -# startswith case insensitive -assert(string.startswith("qwerty", "qw", true) == true) -assert(string.startswith("qwerty", "qwerty", true) == true) -assert(string.startswith("qwerty", "", true) == true) -assert(string.startswith("qwerty", "qW", true) == true) -assert(string.startswith("qwerty", "QW", true) == true) -assert(string.startswith("qwerty", "qz", true) == false) -assert(string.startswith("qwerty", "qwertyw", true) == false) - -# endswith case sensitive -assert(string.endswith("", "") == true) -assert(string.endswith("qwerty", "ty") == true) -assert(string.endswith("qwerty", "qwerty") == true) -assert(string.endswith("qwerty", "") == true) -assert(string.endswith("qwerty", "tY") == false) -assert(string.endswith("qwerty", "TY") == false) -assert(string.endswith("qwerty", "tr") == false) -assert(string.endswith("qwerty", "qwertyw") == false) - -# endswith case insensitive -assert(string.endswith("", "", true) == true) -assert(string.endswith("qwerty", "ty", true) == true) -assert(string.endswith("qwerty", "qwerty", true) == true) -assert(string.endswith("qwerty", "", true) == true) -assert(string.endswith("qwerty", "tY", true) == true) -assert(string.endswith("qwerty", "TY", true) == true) -assert(string.endswith("qwerty", "tr", true) == false) -assert(string.endswith("qwerty", "qwertyw", true) == false) diff --git a/lib/libesp32/Berry/tests/subobject.be b/lib/libesp32/Berry/tests/subobject.be deleted file mode 100644 index 010e8af2984b..000000000000 --- a/lib/libesp32/Berry/tests/subobject.be +++ /dev/null @@ -1,29 +0,0 @@ -class mylist : classof([]) end - -assert(issubclass(mylist, list) == true) -assert(issubclass(mylist, []) == true) -assert(issubclass(mylist(), list) == false) -assert(issubclass(mylist(), []) == false) - -assert(isinstance(mylist, list) == false) -assert(isinstance(mylist, []) == false) -assert(isinstance(mylist(), list) == true) -assert(isinstance(mylist(), []) == true) - -assert(issubclass(list, list) == true) -assert(issubclass(list, []) == true) -assert(issubclass(list(), list) == false) -assert(issubclass(list(), []) == false) - -assert(isinstance(list, list) == false) -assert(isinstance(list, []) == false) -assert(isinstance(list(), list) == true) -assert(isinstance(list(), []) == true) - -assert(issubclass(list, list) == true) -assert(issubclass(list, []) == true) -assert(issubclass(list(), list) == false) -assert(issubclass(list(), []) == false) - -assert(issubclass(list, mylist) == false) -assert(isinstance([], mylist) == false) diff --git a/lib/libesp32/Berry/tests/suffix.be b/lib/libesp32/Berry/tests/suffix.be deleted file mode 100644 index 11f429aa7f70..000000000000 --- a/lib/libesp32/Berry/tests/suffix.be +++ /dev/null @@ -1,28 +0,0 @@ -var keys = [ 'key1', 'key2', 'key3', 'key4' ] -var pairs = { - keys[0]: 'value1', - keys[1]: 'value2', - keys[2]: 'value3', - keys[3]: 'value4' -} - -for i : 0 .. keys.size() - 1 - assert(pairs[keys[i]] == 'value' .. i + 1) -end - -#- test cases related to #101 -# -class C var l end -c=C() -c.l=[0,1,2] - -def t_101_nok_1() return c.l[0..1] end -def t_101_ok_1() var l2 = c.l return l2[0..1] end - -t_i = 0 -def t_101_nok_2() return c.l[t_i] end -def t_101_ok_2() return c.l[0] end - -assert(t_101_nok_1() == [0, 1]) -assert(t_101_ok_1() == [0, 1]) -assert(t_101_nok_2() == 0) -assert(t_101_ok_2() == 0) diff --git a/lib/libesp32/Berry/tests/super_auto.be b/lib/libesp32/Berry/tests/super_auto.be deleted file mode 100644 index 8d7ede85fd6e..000000000000 --- a/lib/libesp32/Berry/tests/super_auto.be +++ /dev/null @@ -1,132 +0,0 @@ -#- test for new auto class inference of super() -# - -#- test that we can call init() even if it's not defined -# -class Z end -z=Z() -assert(z.init != nil) -z.init() #- should do nothing -# - -#- check the old way still works -# -class A1 - var a - def init(a) - self.a = a - end -end -class B1:A1 - var b - def init(a,b) - super(self,A1).init(a) - self.b = b - end -end -class C1:B1 - var c - def init(a,b,c) - super(self,B1).init(a,b) - self.c = c - end -end -#- -# -c1=C1(1,2,3) -assert(c1.a == 1) -assert(c1.b == 2) -assert(c1.c == 3) - -#- test simple behavior -# -class A0 var a end -class B0:A0 var b end -class C0:B0 end -c0=C0() -assert(classof(c0) == C0) -assert(classof(super(c0)) == B0) -assert(classof(super(super(c0))) == A0) -assert(super(super(super(c0))) == nil) - -assert(super(C0) == B0) -assert(super(super(C0)) == A0) -assert(super(super(super(C0))) == nil) - -assert(classof(super(c0,B0)) == B0) -assert(classof(super(c0,A0)) == A0) - -#- test auto inference of target superclass -# -class A - var a - def init(a) - self.a = a - end -end -class B:A - var b - def init(a,b) - super(self).init(a) - self.b = b - end -end -class C:B - var c - def init(a,b,c) - super(self).init(a,b) - self.c = c - end -end -#- -# -c=C(1,2,3) - -assert(c.a == 1) -assert(c.b == 2) -assert(c.c == 3)class A -end -class B:A - var b - def init(a,b) super(self).init(a) self.b = b end -end -class C:B - var c - def init(a,b,c) super(self).init(a,b) self.c = c end -end -c=C(1,2,3) - -#- variant if A2 does not have an init() method, still works -# -class A2 - static a=1 -end -class B2:A2 - var b - def init(a,b) super(self).init(a) self.b = b end -end -class C2:B2 - var c - def init(a,b,c) super(self).init(a,b) self.c = c end -end -#- -# -c2=C2(1,2,3) -assert(c2.a == 1) -assert(c2.b == 2) -assert(c2.c == 3) - -#- difference in behavior whether the second arg is provided or not -# -class A3 -end -class B3:A3 - def b1() - return super(self) - end - def b2(c) - return super(self, c) - end -end -class C3:B3 -end -#- -# -b3=B3() -c3=C3() -assert(classof(c3.b1()) == A3) -assert(classof(b3.b1()) == A3) -assert(classof(c3.b2(B3)) == B3) -assert(classof(c3.b2(A3)) == A3) - -assert(classof(c3.b2(nil)) == B3) #- testing super(self,nil) in B3::b2() -# - -assert(c3.b2(C3) == nil) #- if specifying the current class, can't find any relevant class in supers -# \ No newline at end of file diff --git a/lib/libesp32/Berry/tests/super_leveled.be b/lib/libesp32/Berry/tests/super_leveled.be deleted file mode 100644 index e8891494123b..000000000000 --- a/lib/libesp32/Berry/tests/super_leveled.be +++ /dev/null @@ -1,43 +0,0 @@ -#- test for leveled use of super() -# - -#- setup -# -class A def r() return 'a' end def f() return self.r() end end -class B:A def r() return 'b' end def f() return super(self,A).f() + 'b' end end -class C:B def r() return 'c' end def f() return super(self,B).f() + 'c' end end -a=A() -b=B() -c=C() - -#- regular behavior -# -assert(classname(a) == 'A') -assert(classname(b) == 'B') -assert(classname(c) == 'C') -assert(a.r() == 'a') -assert(b.r() == 'b') -assert(c.r() == 'c') -assert(a.f() == 'a') - -#- standard use of super() -# -assert(super(a) == nil) -assert(super(A) == nil) -assert(classname(super(B)) == 'A') -assert(classname(super(C)) == 'B') -assert(classname(super(super(C))) == 'A') -assert(super(super(super(C))) == nil) - -#- super() levele -# -assert(super(a,A) == nil) -assert(super(b,B) == nil) -assert(super(c,C) == nil) -assert(classname(super(c,B)) == 'B') -assert(classname(super(c,A)) == 'A') -assert(super(c,map) == nil) #- not a parent class -# - -#- wrapping it all -# -assert(a.f() == 'a') -assert(b.f() == 'bb') - -#- the last one is tricky: - c.f() -> calls f() in class B -> calls f() in class A -> calls r() of overall class hence C --# -assert(c.f() == 'cbc') \ No newline at end of file diff --git a/lib/libesp32/Berry/tests/vararg.be b/lib/libesp32/Berry/tests/vararg.be deleted file mode 100644 index 7dd3541d3c48..000000000000 --- a/lib/libesp32/Berry/tests/vararg.be +++ /dev/null @@ -1,14 +0,0 @@ -#- vararg -# -def f(a,*b) return b end - -assert(f() == []) -assert(f(1) == []) -assert(f(1,2) == [2]) -assert(f(1,2,3) == [2, 3]) - -def g(*a) return a end - -assert(g() == []) -assert(g("foo") == ["foo"]) -assert(g("foo", nil) == ["foo", nil]) -assert(g("foo", nil, 2) == ["foo", nil, 2]) diff --git a/lib/libesp32/Berry/tests/virtual_methods.be b/lib/libesp32/Berry/tests/virtual_methods.be deleted file mode 100644 index e744dcca84ee..000000000000 --- a/lib/libesp32/Berry/tests/virtual_methods.be +++ /dev/null @@ -1,72 +0,0 @@ -#- basic initialization -# - -def assert_attribute_error(f) - try - f() - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == 'attribute_error') - end -end - -class T1 - var a, b - def init() - self.a = 1 - self.b = 2 - end - def f() return true end - def g() return false end -end -t = T1() - -#- warm up -# -assert(t.a == 1) -assert(t.b == 2) -assert(t.f() == true) -assert(t.g() == false) - -#- test normal errors when method does not exist -# -assert_attribute_error(/-> t.h()) -assert_attribute_error(/-> t.c) - -class T2 : T1 - def member(n) - import undefined - if (n == 'f1') return / n -> n end - if (n == 'f2') return /-> 4 end - if (n == 'a1') return 10 end - if (n == 'h') return undefined end - end -end -t2 = T2() - -#- test non-regression -# -assert(t2.a == 1) -assert(t2.b == 2) -assert(t2.f() == true) -assert(t2.g() == false) -assert_attribute_error(/-> t2.h()) - -#- try virtual methods -# -assert(t2.f1() == t2) -assert(t2.f2() == 4) -assert(t2.a1 == 10) -assert(t2.foo == nil) - -#- module -# -m = module("m") - -m.a = 1 -assert(m.a == 1) -assert_attribute_error(/-> m.b) - -m.member = def(n) - import undefined - if n == "b" return 2 end - if n == "c" return undefined end -end - -assert(m.b == 2) -assert_attribute_error(/-> m.c) -assert(m.d == nil) #- returns nil if no response -# diff --git a/lib/libesp32/Berry/tests/virtual_methods2.be b/lib/libesp32/Berry/tests/virtual_methods2.be deleted file mode 100644 index 10fee905de92..000000000000 --- a/lib/libesp32/Berry/tests/virtual_methods2.be +++ /dev/null @@ -1,39 +0,0 @@ -#- virtual attributes -# - -def assert_attribute_error(f) - try - f() - assert(false, 'unexpected execution flow') - except .. as e, m - assert(e == 'attribute_error') - end -end - -class Ta - var a, b, virtual_c - def init() - self.a = 1 - self.b = 2 - self.virtual_c = 3 - end - def member(n) - if n == 'c' return self.virtual_c end - return nil - end - def setmember(n, v) - if n == 'c' self.virtual_c = v return true end - return false - end -end -ta = Ta() - -assert(ta.a == 1) -assert(ta.b == 2) -assert(ta.c == 3) -ta.a = 10 -assert(ta.a == 10) -assert(ta.c == 3) -ta.c = 30 -assert(ta.c == 30) -assert(ta.virtual_c == 30) -assert_attribute_error(def() ta.d = 0 end) diff --git a/lib/libesp32/Berry/tools/grammar/berry.bytecode b/lib/libesp32/Berry/tools/grammar/berry.bytecode deleted file mode 100755 index 6b90c2a1d8ae..000000000000 --- a/lib/libesp32/Berry/tools/grammar/berry.bytecode +++ /dev/null @@ -1,92 +0,0 @@ -------------------------------------------------------------------------------- --- the Berry's bytecode file structure (version 1) --- --- description --- --- a double dash ('--') start a line comment. --- a: b means that the entity 'a' is realized by the 'b' structure. --- a: b c 'b' and 'c' are arranged in a compact order (one byte alignment). --- [a] means that structure 'a' can be repeated 0 to any times. --- [a](b) means that structure 'a' can be repeated 'b' times. --- a | b means that the entity can be implemented by structure 'a' or 'b'. --- N a number indicates the byte count of the field (eg. 'a: 1'). --- .N means the number of bits in the field (eg. 'a: .1'). --- only the first entity is a file entity (the root). -------------------------------------------------------------------------------- - -bytecode_file: -- little endian - header - global_desc - main_function - -header: 8 - magic_number: 3 -- 0xbecdfe (berry code file) - version: 1 -- 0x03 update with file structure definition - integer_size: .1 - float_size: .1 - -- reserved space - -main_function -> function - -global_desc: - builtin_count: 4 - global_count: 4 -- excluding builtins - global_name -> [ - string - ](global_count) - -function: - information: - function_name: - string - source: - string - argc: 1 -- arguments count - nstack: 1 -- number of stack size by this function - varg: 1 - extra: 1 -- extra data - bytecode: - code_size: 4 - code_array -> [ -- bytecode array - instruction: 4 - ](code_size) - constant_table: - constant_count: 4 - [constant_value](constant_count) - proto_table: - proto_count: 4 - [function](proto_count) - upval_table: - upval_count: 1 - upvals: [ - instack: 1 - index: 1 - ](upval_count) - debug_info: - -- reserved - -constant_value: - type: 1 -- type of value - integer | float | string | class - -string: - string_size: 2 - byte_array: string_size - -class: - class_name: - string - member_count: 4 -- number of member variables - method_count: 4 -- number of method - method_table: [ - string -- method name - function | nil -- method function body or nil (static member) if the first byte is null (which would be an empty func name) - ](method_count) - member_index_table -> [ - string -- member name - ](member_count) - -nil: 1 -boolean: 1 -integer: 4 | 8 -float: 4 | 8 diff --git a/lib/libesp32/Berry/tools/grammar/berry.ebnf b/lib/libesp32/Berry/tools/grammar/berry.ebnf deleted file mode 100644 index 86eef9b58206..000000000000 --- a/lib/libesp32/Berry/tools/grammar/berry.ebnf +++ /dev/null @@ -1,49 +0,0 @@ -(* program define *) -program = block; -(* block define *) -block = {statement}; -(* statement define *) -statement = class_stmt | func_stmt | var_stmt | if_stmt | while_stmt | - for_stmt | break_stmt | return_stmt | expr_stmt | import_stmt | - try_stmt | throw_stmt | do_stmt | ';'; -if_stmt = 'if' expr block {'elif' expr block} ['else' block] 'end'; -while_stmt = 'while' expr block 'end'; -do_stmt = 'do' block 'end'; -for_stmt = 'for' ID ':' expr block 'end'; -break_stmt = 'break' | 'continue'; -return_stmt = 'return' [expr]; -(* function define statement *) -func_stmt = 'def' ID func_body; -func_body = '(' [arg_field {',' arg_field}] ')' block 'end'; -arg_field = ['*'] ID; -(* class define statement *) -class_stmt = 'class' ID [':' ID] class_block 'end'; -class_block = {'var' ID {',' ID} | 'static' ['var'] ID ['=' expr] {',' ID ['=' expr] } | 'static' func_stmt | func_stmt}; -import_stmt = 'import' (ID (['as' ID] | {',' ID}) | STRING 'as' ID); -(* exceptional handling statement *) -try_stmt = 'try' block except_block {except_block} 'end'; -except_block = except_stmt block; -except_stmt = 'except' (expr {',' expr} | '..') ['as' ID [',' ID]]; -throw_stmt = 'raise' expr [',' expr]; -(* variable define statement *) -var_stmt = 'var' ID ['=' expr] {',' ID ['=' expr]}; -(* expression define *) -expr_stmt = expr [assign_op expr]; -expr = suffix_expr | unop expr | expr binop expr | range_expr | cond_expr | walrus_expr; -cond_expr = expr '?' expr ':' expr; (* conditional expression *) -assign_op = '=' | '+=' | '-=' | '*=' | '/=' | - '%=' | '&=' | '|=' | '^=' | '<<=' | '>>='; -binop = '<' | '<=' | '==' | '!=' | '>' | '>=' | '||' | '&&' | - '<<' | '>>' | '&' | '|' | '^' | '+' | '-' | '*' | '/' | '%'; -range_expr = expr '..' [expr] -unop = '-' | '!' | '~'; -walrus_expr = expr ':=' expr -suffix_expr = primary_expr {call_expr | ('.' ID) | '[' expr ']'}; -primary_expr = '(' expr ')' | simple_expr | list_expr | map_expr | anon_func | lambda_expr; -simple_expr = INTEGER | REAL | STRING | ID | 'true' | 'false' | 'nil' | f_string; -f_string = 'f' STRING -call_expr = '(' [expr {',' expr}] ')'; -list_expr = '[' {expr ','} [expr] ']'; -map_expr = '{' {expr ':' expr ','} [expr ':' expr] '}'; -anon_func = 'def' func_body; (* anonymous function *) -lambda_expr = '/' [arg_field {',' arg_field}] | {arg_field}] '->' expr; diff --git a/lib/libesp32/Berry/tools/grammar/const_obj.ebnf b/lib/libesp32/Berry/tools/grammar/const_obj.ebnf deleted file mode 100755 index 6c38a42624ac..000000000000 --- a/lib/libesp32/Berry/tools/grammar/const_obj.ebnf +++ /dev/null @@ -1,11 +0,0 @@ -block = type name ['(' {attributes} ')'] '{' {data_fields} '}'; -type = 'map' | 'class' | 'module' | 'vartab'; - -attributes = name ':' name [',']; -data_fields = data_name ',' data_value [':' depend_macro] '\n'; - -(* regular expression *) -name = [_a-zA-Z]\w*; -data_name = [\._a-zA-Z]\w*; -data_value = [\w\()]+; -depend_macro = [_a-zA-Z]\w*; diff --git a/lib/libesp32/Berry/tools/grammar/json.ebnf b/lib/libesp32/Berry/tools/grammar/json.ebnf deleted file mode 100644 index 47c317193989..000000000000 --- a/lib/libesp32/Berry/tools/grammar/json.ebnf +++ /dev/null @@ -1,5 +0,0 @@ -json = value; -value = object | array | - string | number | 'true' | 'false' | 'null'; -object = '{' [ string ':' value ] { ',' string ':' value } '}'; -array = '[' [json] { ',' json } ']';