diff --git a/README.md b/README.md index bdd982e9..4152ea6b 100644 --- a/README.md +++ b/README.md @@ -17,149 +17,9 @@ Picrin is a lightweight scheme implementation intended to comply with full R7RS - advanced REPL support (multi-line input, etc) - tiny & portable library (all functions will be in `libpicrin.so`) -## Libraries +## Documentation - - `(scheme base)` - - `(scheme write)` - - `(scheme cxr)` - - `(scheme file)` - - `(scheme inexact)` - - `(scheme time)` - - `(scheme process-context)` - - `(scheme load)` - - `(scheme lazy)` - - `(picrin macro)` - - - `define-macro` - - `gensym` - - `macroexpand` - - Old-fashioned macro. - - - `make-syntactic-closure` - - `identifier?` - - `identifier=?` - - Syntactic closures. - - - `er-macro-transformer` - - `ir-macro-transformer` - - Explicit renaming macro family. - - - `(picrin regexp)` - - - `(regexp? obj)` - - `(regexp ptrn [flags])` - - Compiles pattern string into a regexp object. A string `flags` may contain any of #\g, #\i, #\m. - - - `(regexp-match re input)` - - Returns two values: a list of match strings, and a list of match indeces. - - - `(regexp-replace re input txt)` - - `(regexp-split re input)` - - - `(picrin control)` - - - `(reset h)` - - `(shift k)` - - delimited control operators - - - `(picrin user)` - - When you start the REPL, you are dropped into here. - - - `(srfi 1)` - - List manipulation library. - - - `(srfi 95)` - - Sorting and Marging. - - -## The REPL - -At the REPL start-up time, some usuful built-in libraries listed below will be automatically imported. - -- `(scheme base)` -- `(scheme load)` -- `(scheme process-context)` -- `(scheme write)` -- `(scheme file)` -- `(scheme inexact)` -- `(scheme cxr)` -- `(scheme lazy)` -- `(scheme time)` - -## Compliance with R7RS - -| section | status | comments | -| --- | --- | --- | -| 2.2 Whitespace and comments | yes | | -| 2.3 Other notations | incomplete | #e #i #b #o #d #x | -| 2.4 Datum labels | yes | | -| 3.1 Variables, syntactic keywords, and regions | | | -| 3.2 Disjointness of types | yes | | -| 3.3 External representations | | | -| 3.4 Storage model | yes | | -| 3.5 Proper tail recursion | yes | As the report specifies, `apply`, `call/cc`, and `call-with-values` perform tail calls | -| 4.1.1 Variable references | yes | | -| 4.1.2 Literal expressions | yes | | -| 4.1.3 Procedure calls | yes | In picrin `()` is self-evaluating | -| 4.1.4 Procedures | yes | | -| 4.1.5 Conditionals | yes | In picrin `(if #f #f)` returns `#f` | -| 4.1.6 Assignments | yes | | -| 4.1.7 Inclusion | incomplete | `include-ci`. TODO: Once `read` is implemented rewrite `include` macro with it. | -| 4.2.1 Conditionals | incomplete | TODO: `cond-expand` | -| 4.2.2 Binding constructs | yes | | -| 4.2.3 Sequencing | yes | | -| 4.2.4 Iteration | yes | | -| 4.2.5 Delayed evaluation | N/A | | -| 4.2.6 Dynamic bindings | yes | | -| 4.2.7 Exception handling | no | `guard` syntax. | -| 4.2.8 Quasiquotation | yes | can be safely nested. TODO: multiple argument for unquote | -| 4.2.9 Case-lambda | N/A | | -| 4.3.1 Bindings constructs for syntactic keywords | incomplete | (*1) | -| 4.3.2 Pattern language | yes | `syntax-rules` | -| 4.3.3 Signaling errors in macro transformers | yes | | -| 5.1 Programs | yes | | -| 5.2 Import declarations | incomplete | only simple import declarations, no support for import with renaming. | -| 5.3.1 Top level definitions | yes | | -| 5.3.2 Internal definitions | yes | TODO: interreferential definitions | -| 5.3.3 Multiple-value definitions | yes | | -| 5.4 Syntax definitions | yes | TODO: internal macro definition is not supported. | -| 5.5 Recored-type definitions | yes | | -| 5.6.1 Library Syntax | incomplete | In picrin, libraries can be reopend and can be nested. | -| 5.6.2 Library example | N/A | | -| 5.7 The REPL | yes | | -| 6.1 Equivalence predicates | yes | TODO: equal? must terminate if circular structure is given | -| 6.2.1 Numerical types | yes | picrin has only two types of internal representation of numbers: fixnum and double float. It still comforms the R7RS spec. | -| 6.2.2 Exactness | yes | | -| 6.2.3 Implementation restrictions | yes | | -| 6.2.4 Implementation extensions | yes | | -| 6.2.5 Syntax of numerical constants | yes | | -| 6.2.6 Numerical operations | yes | `denominator`, `numerator`, and `rationalize` are not supported for now. Also, picrin does not provide complex library procedures. | -| 6.2.7 Numerical input and output | incomplete | only partial support supplied. | -| 6.3 Booleans | yes | | -| 6.4 Pairs and lists | yes | `list?` is safe for using against circular list. | -| 6.5 Symbols | yes | | -| 6.6 Characters | yes | | -| 6.7 Strings | yes | | -| 6.8 Vectors | yes | | -| 6.9 Bytevectors | yes | | -| 6.10 Control features | yes | | -| 6.11 Exceptions | yes | `raise-continuable` is not supported | -| 6.12 Environments and evaluation | N/A | | -| 6.13.1 Ports | yes | | -| 6.13.2 Input | yes | | -| 6.13.3 Output | yes | | -| 6.14 System interface | yes | | - -1. Picrin provides hygienic macros in addition to so-called legacy macro (`define-macro`), such as syntactic closure, explicit renaming macro, and implicit renaming macro. As of now let-syntax and letrec-syntax are not provided. +See http://picrin.readthedocs.org/ ## Homepage @@ -216,7 +76,7 @@ Picrin scheme depends on some external libraries to build the binary: - perl - lex (preferably, flex) - getopt -- readline (optional) +- libedit (optional) - regex.h of POSIX.1 (optional) Optional libraries are, if cmake detected them, automatically enabled. diff --git a/cmake/FindLibedit.cmake b/cmake/FindLibedit.cmake new file mode 100644 index 00000000..0acb8607 --- /dev/null +++ b/cmake/FindLibedit.cmake @@ -0,0 +1,89 @@ +# - Try to find libedit +# Once done this will define +# +# Libedit_FOUND - system has libedit +# Libedit_INCLUDE_DIRS - the libedit include directory +# Libedit_LIBRARIES - Link these to use libedit +# Libedit_DEFINITIONS - Compiler switches required for using libedit +# +# Copyright (c) 2014 Yuichi Nishiwaki +# Copyright (c) 2008 Andreas Schneider +# Modified for other libraries by Lasse Kärkkäinen +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# + + +if (Libedit_LIBRARIES AND Libedit_INCLUDE_DIRS) + # in cache already + set(Libedit_FOUND TRUE) +else (Libedit_LIBRARIES AND Libedit_INCLUDE_DIRS) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) + include(UsePkgConfig) + pkgconfig(libedit _Libedit_INCLUDEDIR _Libedit_LIBDIR _Libedit_LDFLAGS _Libedit_CFLAGS) + else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(_LIBEDIT libedit) + endif (PKG_CONFIG_FOUND) + endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4) + find_path(Libedit_INCLUDE_DIR + NAMES + histedit.h + PATHS + ${_Libedit_INCLUDEDIR} + /usr/include + /usr/local/include + /opt/local/include + /sw/include + PATH_SUFFIXES + editline + ) + + find_library(Libedit_LIBRARY + NAMES + edit + PATHS + ${_Libedit_LIBDIR} + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ) + + if (Libedit_LIBRARY) + set(Libedit_FOUND TRUE) + endif (Libedit_LIBRARY) + + set(Libedit_INCLUDE_DIRS + ${Libedit_INCLUDE_DIR} + ) + + if (Libedit_FOUND) + set(Libedit_LIBRARIES + ${Libedit_LIBRARIES} + ${Libedit_LIBRARY} + ) + endif (Libedit_FOUND) + + if (Libedit_INCLUDE_DIRS AND Libedit_LIBRARIES) + set(Libedit_FOUND TRUE) + endif (Libedit_INCLUDE_DIRS AND Libedit_LIBRARIES) + + if (Libedit_FOUND) + if (NOT Libedit_FIND_QUIETLY) + message(STATUS "Found libedit: ${Libedit_LIBRARY}") + endif (NOT Libedit_FIND_QUIETLY) + else (Libedit_FOUND) + if (Libedit_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libedit") + endif (Libedit_FIND_REQUIRED) + endif (Libedit_FOUND) + + # show the Libedit_INCLUDE_DIRS and Libedit_LIBRARIES variables only in the advanced view + mark_as_advanced(Libedit_INCLUDE_DIRS Libedit_LIBRARIES) + +endif (Libedit_LIBRARIES AND Libedit_INCLUDE_DIRS) diff --git a/cmake/FindREADLINE.cmake b/cmake/FindREADLINE.cmake deleted file mode 100644 index 58d6c681..00000000 --- a/cmake/FindREADLINE.cmake +++ /dev/null @@ -1,113 +0,0 @@ -# This file used to be a part of LuaJit project. - -# =============================================================================== -# Picrin Scheme -- a lightweight scheme implementation. - -# Copyright (C) 2014 Yuichi Nishiwaki. All rights reserved. - -# 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. - -# [ MIT license: http://www.opensource.org/licenses/mit-license.php ] - -# =============================================================================== -# LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/ - -# Copyright (C) 2005-2013 Mike Pall. All rights reserved. - -# 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. - -# [ MIT license: http://www.opensource.org/licenses/mit-license.php ] - -# =============================================================================== -# [ LuaJIT includes code from Lua 5.1/5.2, which has this license statement: ] - -# Copyright (C) 1994-2012 Lua.org, PUC-Rio. - -# 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. - -# =============================================================================== -# [ LuaJIT includes code from dlmalloc, which has this license statement: ] - -# This is a version (aka dlmalloc) of malloc/free/realloc written by -# Doug Lea and released to the public domain, as explained at -# http://creativecommons.org/licenses/publicdomain - -# =============================================================================== - - - -# - Try to find Readline -# Once done this will define -# READLINE_FOUND - System has readline -# READLINE_INCLUDE_DIRS - The readline include directories -# READLINE_LIBRARIES - The libraries needed to use readline -# READLINE_DEFINITIONS - Compiler switches required for using readline - -find_package ( PkgConfig ) -pkg_check_modules ( PC_READLINE QUIET readline ) -set ( READLINE_DEFINITIONS ${PC_READLINE_CFLAGS_OTHER} ) - -find_path ( READLINE_INCLUDE_DIR readline/readline.h - HINTS ${PC_READLINE_INCLUDEDIR} ${PC_READLINE_INCLUDE_DIRS} - PATH_SUFFIXES readline ) - -find_library ( READLINE_LIBRARY NAMES readline - HINTS ${PC_READLINE_LIBDIR} ${PC_READLINE_LIBRARY_DIRS} ) - -set ( READLINE_LIBRARIES ${READLINE_LIBRARY} ) -set ( READLINE_INCLUDE_DIRS ${READLINE_INCLUDE_DIR} ) - -include ( FindPackageHandleStandardArgs ) -# handle the QUIETLY and REQUIRED arguments and set READLINE_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args ( readline DEFAULT_MSG READLINE_LIBRARY READLINE_INCLUDE_DIR ) - -mark_as_advanced ( READLINE_INCLUDE_DIR READLINE_LIBRARY ) diff --git a/docs/lang.rst b/docs/lang.rst index 7a856a74..9d6c6786 100644 --- a/docs/lang.rst +++ b/docs/lang.rst @@ -85,3 +85,72 @@ At the REPL start-up time, some usuful built-in libraries listed below will be a - ``(scheme cxr)`` - ``(scheme lazy)`` - ``(scheme time)`` + +Compiliance with R7RS +--------------------- + +================================================ ========== ========================================================================================================================== +section status comments +================================================ ========== ========================================================================================================================== +2.2 Whitespace and comments yes +2.3 Other notations incomplete #e #i #b #o #d #x +2.4 Datum labels yes +3.1 Variables, syntactic keywords, and regions +3.2 Disjointness of types yes +3.3 External representations +3.4 Storage model yes +3.5 Proper tail recursion yes As the report specifies, ``apply``, ``call/cc``, and ``call-with-values`` perform tail calls +4.1.1 Variable references yes +4.1.2 Literal expressions yes +4.1.3 Procedure calls yes In picrin ``()`` is self-evaluating +4.1.4 Procedures yes +4.1.5 Conditionals yes In picrin ``(if #f #f)`` returns ``#f`` +4.1.6 Assignments yes +4.1.7 Inclusion incomplete ``include-ci``. TODO: Once ``read`` is implemented rewrite ``include`` macro with it. +4.2.1 Conditionals incomplete TODO: ``cond-expand`` +4.2.2 Binding constructs yes +4.2.3 Sequencing yes +4.2.4 Iteration yes +4.2.5 Delayed evaluation N/A +4.2.6 Dynamic bindings yes +4.2.7 Exception handling no ``guard`` syntax. +4.2.8 Quasiquotation yes can be safely nested. TODO: multiple argument for unquote +4.2.9 Case-lambda N/A +4.3.1 Bindings constructs for syntactic keywords incomplete [#]_ +4.3.2 Pattern language yes ``syntax-rules`` +4.3.3 Signaling errors in macro transformers yes +5.1 Programs yes +5.2 Import declarations incomplete only simple import declarations, no support for import with renaming. +5.3.1 Top level definitions yes +5.3.2 Internal definitions yes TODO: interreferential definitions +5.3.3 Multiple-value definitions yes +5.4 Syntax definitions yes TODO: internal macro definition is not supported. +5.5 Recored-type definitions yes +5.6.1 Library Syntax incomplete In picrin, libraries can be reopend and can be nested. +5.6.2 Library example N/A +5.7 The REPL yes +6.1 Equivalence predicates yes TODO: equal? must terminate if circular structure is given +6.2.1 Numerical types yes picrin has only two types of internal representation of numbers: fixnum and double float. It still comforms the R7RS spec. +6.2.2 Exactness yes +6.2.3 Implementation restrictions yes +6.2.4 Implementation extensions yes +6.2.5 Syntax of numerical constants yes +6.2.6 Numerical operations yes ``denominator``, ``numerator``, and ``rationalize`` are not supported for now. Also, picrin does not provide complex library procedures. +6.2.7 Numerical input and output incomplete only partial support supplied. +6.3 Booleans yes +6.4 Pairs and lists yes ``list?`` is safe for using against circular list. +6.5 Symbols yes +6.6 Characters yes +6.7 Strings yes +6.8 Vectors yes +6.9 Bytevectors yes +6.10 Control features yes +6.11 Exceptions yes ``raise-continuable`` is not supported +6.12 Environments and evaluation N/A +6.13.1 Ports yes +6.13.2 Input yes +6.13.3 Output yes +6.14 System interface yes +================================================ ========== ========================================================================================================================== + +.. [#] Picrin provides hygienic macros in addition to so-called legacy macro (``define-macro``), such as syntactic closure, explicit renaming macro, and implicit renaming macro. As of now let-syntax and letrec-syntax are not provided. diff --git a/include/picrin.h b/include/picrin.h index fa84f59b..d194de1f 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -105,8 +105,8 @@ typedef struct { struct pic_jmpbuf *try_jmps; struct pic_heap *heap; - struct pic_object *arena[PIC_ARENA_SIZE]; - int arena_idx; + struct pic_object **arena; + size_t arena_size, arena_idx; char *native_stack_start; } pic_state; @@ -123,8 +123,8 @@ void pic_free(pic_state *, void *); void pic_gc_run(pic_state *); pic_value pic_gc_protect(pic_state *, pic_value); -int pic_gc_arena_preserve(pic_state *); -void pic_gc_arena_restore(pic_state *, int); +size_t pic_gc_arena_preserve(pic_state *); +void pic_gc_arena_restore(pic_state *, size_t); pic_state *pic_open(int argc, char *argv[], char **envp); void pic_close(pic_state *); diff --git a/include/picrin/cont.h b/include/picrin/cont.h index a4b8f32a..496454fd 100644 --- a/include/picrin/cont.h +++ b/include/picrin/cont.h @@ -26,7 +26,8 @@ struct pic_cont { pic_code *ip; - struct pic_object *arena[PIC_ARENA_SIZE]; + struct pic_object **arena; + size_t arena_size; int arena_idx; pic_value results; diff --git a/piclib/built-in.scm b/piclib/built-in.scm index ddb175eb..6210136f 100644 --- a/piclib/built-in.scm +++ b/piclib/built-in.scm @@ -263,10 +263,14 @@ ,(let loop ((clauses clauses)) (if (null? clauses) #f - `(,(r 'if) (,(r 'or) - ,@(map (lambda (x) `(,(r 'eqv?) ,(r 'key) (,(r 'quote) ,x))) - (caar clauses))) - (begin ,@(cdar clauses)) + `(,(r 'if) ,(if (compare (r 'else) (caar clauses)) + '#t + `(,(r 'or) + ,@(map (lambda (x) `(,(r 'eqv?) ,(r 'key) (,(r 'quote) ,x))) + (caar clauses)))) + ,(if (compare (r '=>) (cadar clauses)) + `(,(caddar clauses) ,(r 'key)) + `(,(r 'begin) ,@(cdar clauses))) ,(loop (cdr clauses)))))))))) (define-syntax syntax-error diff --git a/src/codegen.c b/src/codegen.c index ef9bd216..5e091d07 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -266,7 +266,7 @@ static pic_value analyze(analyze_state *state, pic_value obj, bool tailpos) { pic_state *pic = state->pic; - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value res; pic_sym tag; @@ -561,7 +561,7 @@ analyze_add(analyze_state *state, pic_value obj, bool tailpos) ARGC_ASSERT_GE(0); switch (pic_length(pic, obj)) { case 1: - return pic_int_value(0); + return pic_list2(pic, pic_symbol_value(pic->sQUOTE), pic_int_value(0)); case 2: return analyze(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); default: @@ -598,7 +598,7 @@ analyze_mul(analyze_state *state, pic_value obj, bool tailpos) ARGC_ASSERT_GE(0); switch (pic_length(pic, obj)) { case 1: - return pic_int_value(1); + return pic_list2(pic, pic_symbol_value(pic->sQUOTE), pic_int_value(1)); case 2: return analyze(state, pic_car(pic, pic_cdr(pic, obj)), tailpos); default: @@ -1438,7 +1438,7 @@ struct pic_proc * pic_compile(pic_state *pic, pic_value obj) { struct pic_irep *irep; - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); #if DEBUG fprintf(stdout, "ai = %d\n", pic_gc_arena_preserve(pic)); diff --git a/src/cont.c b/src/cont.c index e22bcfef..f84e55c7 100644 --- a/src/cont.c +++ b/src/cont.c @@ -139,7 +139,9 @@ save_cont(pic_state *pic, struct pic_cont **c) cont->ip = pic->ip; cont->arena_idx = pic->arena_idx; - memcpy(cont->arena, pic->arena, sizeof(struct pic_object *) * PIC_ARENA_SIZE); + cont->arena_size = pic->arena_size; + cont->arena = (struct pic_object **)pic_alloc(pic, sizeof(struct pic_object *) * pic->arena_size); + memcpy(cont->arena, pic->arena, sizeof(struct pic_object *) * pic->arena_size); cont->results = pic_undef_value(); } @@ -182,7 +184,9 @@ restore_cont(pic_state *pic, struct pic_cont *cont) pic->ip = cont->ip; - memcpy(pic->arena, cont->arena, sizeof(struct pic_object *) * PIC_ARENA_SIZE); + pic->arena = (struct pic_object **)pic_realloc(pic, pic->arena, sizeof(struct pic_object *) * cont->arena_size); + memcpy(pic->arena, cont->arena, sizeof(struct pic_object *) * cont->arena_size); + pic->arena_size = cont->arena_size; pic->arena_idx = cont->arena_idx; memcpy(cont->stk_pos, cont->stk_ptr, cont->stk_len); diff --git a/src/debug.c b/src/debug.c index 7ce89fc0..f59a4125 100644 --- a/src/debug.c +++ b/src/debug.c @@ -10,7 +10,7 @@ pic_str * pic_get_backtrace(pic_state *pic) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_callinfo *ci; pic_str *trace; @@ -38,7 +38,7 @@ pic_get_backtrace(pic_state *pic) void pic_print_backtrace(pic_state *pic, struct pic_error *e) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_str *trace; assert(pic->err != NULL); diff --git a/src/gc.c b/src/gc.c index fd48833e..2821be35 100644 --- a/src/gc.c +++ b/src/gc.c @@ -179,8 +179,9 @@ pic_free(pic_state *pic, void *ptr) static void gc_protect(pic_state *pic, struct pic_object *obj) { - if (pic->arena_idx >= PIC_ARENA_SIZE) { - pic_abort(pic, "arena overflow"); + if (pic->arena_idx >= pic->arena_size) { + pic->arena_size = pic->arena_size * 2 + 1; + pic->arena = pic_realloc(pic, pic->arena, sizeof(struct pic_object *) * pic->arena_size); } pic->arena[pic->arena_idx++] = obj; } @@ -200,14 +201,14 @@ pic_gc_protect(pic_state *pic, pic_value v) return v; } -int +size_t pic_gc_arena_preserve(pic_state *pic) { return pic->arena_idx; } void -pic_gc_arena_restore(pic_state *pic, int state) +pic_gc_arena_restore(pic_state *pic, size_t state) { pic->arena_idx = state; } @@ -618,6 +619,7 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) pic_free(pic, cont->stk_ptr); pic_free(pic, cont->st_ptr); pic_free(pic, cont->ci_ptr); + pic_free(pic, cont->arena); PIC_BLK_DECREF(pic, cont->blk); break; } diff --git a/src/init.c b/src/init.c index 8bbc3229..26050194 100644 --- a/src/init.c +++ b/src/init.c @@ -60,7 +60,7 @@ pic_features(pic_state *pic) void pic_init_core(pic_state *pic) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_deflibrary ("(scheme base)") { diff --git a/src/load.c b/src/load.c index ec95b4dc..b1fcf39a 100644 --- a/src/load.c +++ b/src/load.c @@ -8,7 +8,7 @@ pic_value pic_load_cstr(pic_state *pic, const char *src) { - int ai; + size_t ai; pic_value v, exprs; struct pic_proc *proc; @@ -37,7 +37,7 @@ pic_value pic_load(pic_state *pic, const char *fn) { FILE *file; - int ai; + size_t ai; pic_value v, exprs; struct pic_proc *proc; diff --git a/src/macro.c b/src/macro.c index b4a33a5a..2790efb0 100644 --- a/src/macro.c +++ b/src/macro.c @@ -150,7 +150,7 @@ static pic_value macroexpand_node(pic_state *, pic_value, struct pic_senv *, pic static pic_value macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv, pic_value assoc_box) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value v; v = macroexpand_node(pic, expr, senv, assoc_box); @@ -196,7 +196,7 @@ push_scope(pic_state *pic, pic_value formals, struct pic_senv *up, pic_value ass static pic_value macroexpand_list(pic_state *pic, pic_value list, struct pic_senv *senv, pic_value assoc_box) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value v, vs; /* macroexpand in order */ @@ -271,7 +271,7 @@ macroexpand_deflibrary(pic_state *pic, pic_value expr) pic_in_library(pic, pic_cadr(pic, expr)); pic_for_each (v, pic_cddr(pic, expr)) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_eval(pic, v); diff --git a/src/number.c b/src/number.c index a73eb785..fb9a4c1f 100644 --- a/src/number.c +++ b/src/number.c @@ -734,7 +734,7 @@ pic_number_string_to_number(pic_state *pic) void pic_init_number(pic_state *pic) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_defun(pic, "number?", pic_number_real_p); pic_defun(pic, "complex?", pic_number_real_p); diff --git a/src/pair.c b/src/pair.c index 37d5ff7f..6fe316c1 100644 --- a/src/pair.c +++ b/src/pair.c @@ -84,7 +84,7 @@ pic_list1(pic_state *pic, pic_value obj1) pic_value pic_list2(pic_state *pic, pic_value obj1, pic_value obj2) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value val; val = pic_cons(pic, obj1, pic_list1(pic, obj2)); @@ -97,7 +97,7 @@ pic_list2(pic_state *pic, pic_value obj1, pic_value obj2) pic_value pic_list3(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value val; val = pic_cons(pic, obj1, pic_list2(pic, obj2, obj3)); @@ -110,7 +110,7 @@ pic_list3(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3) pic_value pic_list4(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3, pic_value obj4) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value val; val = pic_cons(pic, obj1, pic_list3(pic, obj2, obj3, obj4)); @@ -123,7 +123,7 @@ pic_list4(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3, pic_va pic_value pic_list5(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3, pic_value obj4, pic_value obj5) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value val; val = pic_cons(pic, obj1, pic_list4(pic, obj2, obj3, obj4, obj5)); @@ -136,7 +136,7 @@ pic_list5(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3, pic_va pic_value pic_list6(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3, pic_value obj4, pic_value obj5, pic_value obj6) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value val; val = pic_cons(pic, obj1, pic_list5(pic, obj2, obj3, obj4, obj5, obj6)); @@ -149,7 +149,7 @@ pic_list6(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3, pic_va pic_value pic_list7(pic_state *pic, pic_value obj1, pic_value obj2, pic_value obj3, pic_value obj4, pic_value obj5, pic_value obj6, pic_value obj7) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value val; val = pic_cons(pic, obj1, pic_list6(pic, obj2, obj3, obj4, obj5, obj6, obj7)); @@ -205,7 +205,7 @@ pic_length(pic_state *pic, pic_value obj) pic_value pic_reverse(pic_state *pic, pic_value list) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value v, acc; acc = pic_nil_value(); @@ -221,7 +221,7 @@ pic_reverse(pic_state *pic, pic_value list) pic_value pic_append(pic_state *pic, pic_value xs, pic_value ys) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value x; xs = pic_reverse(pic, xs); diff --git a/src/read.c b/src/read.c index e768c10e..030ee0e3 100644 --- a/src/read.c +++ b/src/read.c @@ -217,7 +217,7 @@ read_datum(int tok, yyscan_t scanner) static pic_value read(int tok, yyscan_t scanner) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_value val; val = read_datum(tok, scanner); diff --git a/src/state.c b/src/state.c index 37fab568..a9a13ba8 100644 --- a/src/state.c +++ b/src/state.c @@ -18,7 +18,7 @@ pic_open(int argc, char *argv[], char **envp) char t; pic_state *pic; - int ai; + size_t ai; pic = (pic_state *)malloc(sizeof(pic_state)); @@ -70,6 +70,8 @@ pic_open(int argc, char *argv[], char **envp) pic->try_jmps = NULL; /* GC arena */ + pic->arena = (struct pic_object **)calloc(PIC_ARENA_SIZE, sizeof(struct pic_object **)); + pic->arena_size = PIC_ARENA_SIZE; pic->arena_idx = 0; /* native stack marker */ @@ -153,6 +155,9 @@ pic_close(pic_state *pic) xh_destroy(&pic->global_tbl); xh_destroy(&pic->macros); + /* free GC arena */ + free(pic->arena); + /* free symbol names */ xh_begin(&it, &pic->sym_names); while (xh_next(&it)) { diff --git a/src/system.c b/src/system.c index b5108af1..efd53f48 100644 --- a/src/system.c +++ b/src/system.c @@ -18,7 +18,7 @@ pic_system_cmdline(pic_state *pic) pic_get_args(pic, ""); for (i = 0; i < pic->argc; ++i) { - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); v = pic_cons(pic, pic_obj_value(pic_str_new_cstr(pic, pic->argv[i])), v); pic_gc_arena_restore(pic, ai); @@ -95,7 +95,7 @@ pic_system_getenvs(pic_state *pic) { char **envp; pic_value data = pic_nil_value(); - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); pic_get_args(pic, ""); diff --git a/src/vm.c b/src/vm.c index 760a63eb..6c89d8a8 100644 --- a/src/vm.c +++ b/src/vm.c @@ -514,7 +514,7 @@ pic_value pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv) { pic_code c; - int ai = pic_gc_arena_preserve(pic); + size_t ai = pic_gc_arena_preserve(pic); size_t argc, i; pic_code boot[2]; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 0c5d93d7..54276bde 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,10 +1,10 @@ list(APPEND REPL_LIBRARIES picrin) -find_package(READLINE) -if (READLINE_FOUND) - include_directories(${READLINE_INCLUDE_DIRS}) - add_definitions(${READLINE_DEFINITIONS} -DPIC_READLINE_FOUND=1) - list(APPEND REPL_LIBRARIES ${READLINE_LIBRARIES}) +find_package(LIBEDIT) +if (Libedit_FOUND) + include_directories(${Libedit_INCLUDE_DIRS}) + add_definitions(${Libedit_DEFINITIONS} -DPIC_READLINE_FOUND=1) + list(APPEND REPL_LIBRARIES ${Libedit_LIBRARIES}) endif() # build diff --git a/tools/main.c b/tools/main.c index c65582f5..2d3a8cfd 100644 --- a/tools/main.c +++ b/tools/main.c @@ -13,8 +13,7 @@ #include "picrin/error.h" #if PIC_ENABLE_READLINE -# include -# include +# include #endif #define CODE_MAX_LENGTH 1024