├── test └── com │ └── github │ └── chungkwong │ └── jschememin │ ├── to_include.scm │ ├── lib-dec.scm │ ├── lib-content.scm │ ├── EmbedTest.java │ ├── SchemeAssert.java │ └── lib-example.scm ├── doc ├── .gitignore ├── checkindex.sh ├── repository.tex ├── Makefile ├── genstdmod.pl ├── features.tex ├── r7rs.tex ├── r7rs-ebook.tex ├── overview.tex ├── extract.scm └── example.tex ├── .gitignore ├── manifest.mf ├── src └── com │ └── github │ └── chungkwong │ └── jschememin │ ├── lib │ ├── null.scm │ ├── hashtables_derive.scm │ ├── file_derive.scm │ ├── case-lambda.scm │ ├── NativeProcedure.java │ ├── Lazy.java │ ├── jschememin_derive.scm │ ├── REPL.java │ ├── lazy.scm │ ├── Read.java │ ├── Time.java │ ├── Eval.java │ ├── cxr.scm │ ├── NativeEvaluable.java │ ├── NativeEvaluableMulti.java │ ├── Complex.java │ ├── NativeProcedureDefault.java │ ├── JSchemeMin.java │ ├── Write.java │ ├── SimpleLibrary.java │ ├── ProcessContext.java │ ├── Load.java │ ├── File.java │ ├── Inexact.java │ ├── r5rs.scm │ ├── Char.java │ ├── HashTable.java │ └── NativeLibrary.java │ ├── Token.java │ ├── HELP │ ├── Primitive.java │ ├── DatumLabelSrc.java │ ├── DatumLabelRef.java │ ├── type │ ├── ScmPairOrNil.java │ ├── ScmNumber.java │ ├── ScmNil.java │ ├── ScmEndOfFileObject.java │ ├── ScmObject.java │ ├── ScmUniqueSymbol.java │ ├── ScmBoolean.java │ ├── ScmSymbol.java │ ├── ScmPort.java │ ├── ScmListBuilder.java │ ├── ScmComplexPolar.java │ ├── ScmComplexRectangular.java │ ├── ScmRecord.java │ ├── ObjectPair.java │ ├── ScmNormalReal.java │ ├── ScmProcedure.java │ ├── ScmBinaryOutputPort.java │ ├── DatumRecord.java │ ├── ScmError.java │ ├── ScmPair.java │ └── ScmBinaryInputPort.java │ ├── LibraryLoader.java │ ├── LexicalException.java │ ├── primitive │ ├── UncaughtExceptionError.java │ ├── Quote.java │ ├── Eval.java │ ├── SyntaxRule.java │ ├── Lambda.java │ ├── CallWithValues.java │ ├── WithExceptionHandler.java │ ├── Assignment.java │ ├── RaiseContinuable.java │ ├── Apply.java │ ├── Raise.java │ ├── If.java │ ├── DefineValues.java │ ├── CallWithCurrentContinuation.java │ ├── Include.java │ ├── Define.java │ ├── DefineRecordType.java │ ├── DynamicWind.java │ └── Import.java │ ├── SyntaxException.java │ ├── SimpleToken.java │ ├── BasicConstruct.java │ ├── DatumLabel.java │ ├── Feature.java │ ├── Evaluable.java │ ├── Main.java │ ├── JavaEnvironment.java │ ├── Evaluator.java │ ├── Library.java │ ├── SchemeEnvironment.java │ ├── EvaluatorFactory.java │ ├── Environment.java │ └── LibraryManager.java ├── nbproject ├── genfiles.properties ├── project.xml └── project.properties └── pom.xml /test/com/github/chungkwong/jschememin/to_include.scm: -------------------------------------------------------------------------------- 1 | 12 -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | *.aux 3 | *.idx 4 | *.toc 5 | *.log 6 | *.out 7 | -------------------------------------------------------------------------------- /test/com/github/chungkwong/jschememin/lib-dec.scm: -------------------------------------------------------------------------------- 1 | (export x) 2 | (export y) -------------------------------------------------------------------------------- /test/com/github/chungkwong/jschememin/lib-content.scm: -------------------------------------------------------------------------------- 1 | (define y 3) 2 | (define x 4) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | /build/ 3 | /manifest.mf 4 | /.jacocoverage 5 | jacoco* 6 | /nbproject/private/ -------------------------------------------------------------------------------- /manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | X-COMMENT: Main-Class will be added automatically by build 3 | 4 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/null.scm: -------------------------------------------------------------------------------- 1 | (define-library (scheme null) 2 | (import (scheme base)) 3 | (export and begin case cond define define-syntax delay do if lambda let let* let-syntax letrec letrec-syntax 4 | or quasiquote quote set!)) -------------------------------------------------------------------------------- /nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=bfe0352b 2 | build.xml.script.CRC32=622d1762 3 | build.xml.stylesheet.CRC32=8064a381@1.75.2.48 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=bfe0352b 7 | nbproject/build-impl.xml.script.CRC32=ff24281b 8 | nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48 9 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/hashtables_derive.scm: -------------------------------------------------------------------------------- 1 | (import (scheme base)) 2 | (import (scheme case-lambda)) 3 | (define make-eq-hashtable 4 | (case-lambda 5 | (() (make-hashtable equal-hash eq?)) 6 | ((k) (make-hashtable equal-hash eq? k)))) 7 | (define make-eqv-hashtable 8 | (case-lambda 9 | (() (make-hashtable equal-hash eqv?)) 10 | ((k) (make-hashtable equal-hash eq? k)))) 11 | (define (hashtable-update! hashtable key proc default) 12 | (hashtable-set! hashtable key (proc (hashtable-ref hashtable key default)))) -------------------------------------------------------------------------------- /nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.java.j2seproject 4 | 5 | 6 | JSchemeMin 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /doc/checkindex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Diff the `tt' entries (identifiers) in the generated index.tex 4 | # (excepting certain special cases like library declarations) with the 5 | # identifiers in the library index, to verify they agree. 6 | 7 | diff <(perl -ne 'print if s/^\\item{\\tt{\\?([^{} ]*)}.*$/\1/' index.tex \ 8 | | grep -E -v "^([!',.;?\`]|->|,@|body|catch|except|define-library|export|include-library-declarations|nil|only|prefix|rename|setcar|car-internal)\$" | sort -u) \ 9 | <(./genstdmod.pl --list < stdmod-raw.tex | sort -u | egrep -v 'exact->inexact|inexact->exact') \ 10 | && echo "Library and identifier indexes are consistent." 11 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Token.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | 17 | /** 18 | * The interface for lexer token 19 | * @author Chan Chung Kwong <1m02math@126.com> 20 | */ 21 | public interface Token{ 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/HELP: -------------------------------------------------------------------------------- 1 | Available commands: 2 | step 3 | Move to the next execution state 4 | step in 5 | If a expression is going to be executed, move to the execution state just before a subexpression is evaluated 6 | step over 7 | If a expression is going to be executed, move to the execution state just after the expression is evaluated 8 | run 9 | Move to the first execution state that a breakpoint expression is going to be evaluated 10 | eval EXPR 11 | Evaluate a Scheme expression EXPR in the current environment 12 | stack 13 | Show the execution stack of the current state 14 | list 15 | Show the indices corresponding to each expression as well as the expression is evaluated or not 16 | break add INDEX 17 | Set the expression with index INDEX as a breakpoint 18 | break remove INDEX 19 | Unset the expression with index INDEX as a breakpoint 20 | help 21 | Show this help 22 | quit 23 | Exit this debugger -------------------------------------------------------------------------------- /doc/repository.tex: -------------------------------------------------------------------------------- 1 | \extrapart{Additional material} 2 | 3 | %%The Internet Scheme Repository at 4 | %%\begin{center} 5 | %%{\cf http://www.cs.indiana.edu/scheme-repository/} 6 | %%\end{center} 7 | %%contains an extensive Scheme bibliography, as well as papers, 8 | %%programs, implementations, and other material related to Scheme. 9 | %% Removed as only of historical interest; schemers.org links to it. 10 | 11 | The Scheme community website at 12 | {\cf http://schemers.org} 13 | contains additional resources for learning and programming, job and 14 | event postings, and Scheme user group information. 15 | 16 | A bibliography of Scheme-related research at 17 | {\cf http://library.readscheme.org} 18 | links to technical papers and theses related to the Scheme language, 19 | including both classic papers and recent research. 20 | 21 | On-line Scheme discussions are held using IRC 22 | on the {\cf \#scheme} channel at {\cf irc.freenode.net} 23 | and on the Usenet discussion group {\cf comp.lang.scheme}. 24 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Primitive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | 19 | /** 20 | * Interface for primitive 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public interface Primitive{ 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/file_derive.scm: -------------------------------------------------------------------------------- 1 | (import (scheme base)) 2 | 3 | (define (call-with-input-file file proc) 4 | (call-with-port (open-input-file file) proc)) 5 | (define (call-with-output-file file proc) 6 | (call-with-port (open-output-file file) proc)) 7 | 8 | (define (with-input-from-file file thunk) 9 | (let ((port (open-input-file file)) 10 | (old (current-input-port))) 11 | (dynamic-wind (lambda () (set! old (current-input-port)) (set-current-input-port! port)) 12 | (lambda () (let ((ret (thunk))) (close-port port) ret)) 13 | (lambda () (set-current-input-port! old))))) 14 | (define (with-output-to-file file thunk) 15 | (let ((port (open-output-file file)) 16 | (old (current-output-port))) 17 | (dynamic-wind (lambda () (set! old (current-output-port)) (set-current-output-port! port)) 18 | (lambda () (let ((ret (thunk))) (close-port port) ret)) 19 | (lambda () (set-current-output-port! old))))) -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/DatumLabelSrc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015,2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | /** 17 | * Represents labels to be referenced 18 | * @author kwong 19 | */ 20 | public final class DatumLabelSrc extends DatumLabel{ 21 | /** 22 | * Create a label 23 | * @param label ID 24 | */ 25 | public DatumLabelSrc(String label){ 26 | super(label); 27 | } 28 | @Override 29 | public String toString(){ 30 | return "#"+getLabel()+"="; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/DatumLabelRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015,2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | /** 17 | * Represents labels that reference other label 18 | * @author kwong 19 | */ 20 | public final class DatumLabelRef extends DatumLabel{ 21 | /** 22 | * Create a label 23 | * @param label ID 24 | */ 25 | public DatumLabelRef(String label){ 26 | super(label); 27 | } 28 | @Override 29 | public String toString(){ 30 | return "#"+getLabel()+"#"; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmPairOrNil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | /** 19 | * Represents the type list in Scheme 20 | * @author kwong 21 | */ 22 | public abstract class ScmPairOrNil extends ScmObject{ 23 | @Override 24 | public boolean isSelfevaluating(){ 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmNumber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin.type; 16 | import com.github.chungkwong.jschememin.*; 17 | /** 18 | * Represents the type number in Scheme 19 | * @author kwong 20 | */ 21 | public abstract class ScmNumber extends ScmObject implements Token{ 22 | /** 23 | * Check if the number is a exact number 24 | * @return the result 25 | */ 26 | public abstract boolean isExact(); 27 | @Override 28 | public boolean isSelfevaluating(){ 29 | return true; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmNil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | /** 19 | * Represents the type null in Scheme 20 | * @author kwong 21 | */ 22 | public final class ScmNil extends ScmPairOrNil{ 23 | /** 24 | * The null value 25 | */ 26 | public static final ScmNil NIL=new ScmNil(); 27 | private ScmNil(){ 28 | } 29 | @Override 30 | public String toExternalRepresentation(){ 31 | return "()"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/LibraryLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | /** 20 | * Loader for library 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public interface LibraryLoader{ 24 | /** 25 | * Get the library 26 | * @return 27 | */ 28 | Library getLibrary(); 29 | /** 30 | * The name of the library that this loader load 31 | * @return 32 | */ 33 | ScmPair getName(); 34 | } 35 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/case-lambda.scm: -------------------------------------------------------------------------------- 1 | (define-library (scheme case-lambda) 2 | (import (scheme base)) 3 | (export case-lambda) 4 | (begin 5 | (define-syntax case-lambda 6 | (syntax-rules () 7 | ((case-lambda (params body0 ...) ...) 8 | (lambda args 9 | (let ((len (length args))) 10 | (letrec-syntax 11 | ((cl (syntax-rules ::: () 12 | ((cl) 13 | (error "no matching clause")) 14 | ((cl ((p :::) . body) . rest) 15 | (if (= len (length '(p :::))) 16 | (apply (lambda (p :::) 17 | . body) 18 | args) 19 | (cl . rest))) 20 | ((cl ((p ::: . tail) . body) 21 | . rest) 22 | (if (>= len (length '(p :::))) 23 | (apply 24 | (lambda (p ::: . tail) 25 | . body) 26 | args) 27 | (cl . rest)))))) 28 | (cl (params body0 ...) ...))))))))) 29 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/LexicalException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | 17 | /** 18 | * Lexical exception when reading script source code 19 | * @author Chan Chung Kwong <1m02math@126.com> 20 | */ 21 | public class LexicalException extends RuntimeException { 22 | /** 23 | * Creates a new instance of LexicalException without detail message. 24 | */ 25 | public LexicalException() { 26 | } 27 | /** 28 | * Constructs an instance of LexicalException with the specified detail message. 29 | * @param msg the detail message. 30 | */ 31 | public LexicalException(String msg) { 32 | super(msg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/NativeProcedure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.type.*; 19 | /** 20 | * Represents the dynamic part of a native procedure 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public interface NativeProcedure{ 24 | /** 25 | * To be called when the procedure is called 26 | * @param param 27 | * @return 28 | * @throws Exception 29 | */ 30 | ScmObject call(ScmObject param) throws Exception; 31 | } 32 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Lazy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | /** 20 | * Correspoding to the library (scheme lazy) in Scheme 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class Lazy extends NativeLibrary{ 24 | public static final Lazy INSTANCE=new Lazy(); 25 | private Lazy(){ 26 | super("scheme","lazy"); 27 | } 28 | @Override 29 | protected void init(Library lib){ 30 | addDeriveFile("/com/github/chungkwong/jschememin/lib/lazy.scm"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/jschememin_derive.scm: -------------------------------------------------------------------------------- 1 | (import (scheme base)) 2 | (import (scheme hashtables)) 3 | (define duration (syntax-rules () ((_ x) (let ((t (thread-clock))) x (- (thread-clock) t))))) 4 | (define-record-type (make-call-record count total-time) call-record? 5 | (count count set-count!) (total-time total-time set-total-time!)) 6 | (define statistics (make-eq-hashtable)) 7 | (define profile-lambda 8 | (syntax-rules () 9 | ((_ args body ...) 10 | (letrec ((proc (lambda args 11 | (let* ((t (thread-clock)) (ret (begin body ... ))) 12 | (hashtable-update! statistics 13 | proc 14 | (lambda (e) (set-total-time! e (+ (total-time e) (- (thread-clock) t))) 15 | (set-count! e (+ (count e) 1)) 16 | e) 17 | (make-call-record 0 0)) 18 | ret)))) 19 | proc)))) 20 | (define (profile-record proc) (hashtable-ref statistics proc (make-call-record 0 0))) 21 | (define (profile-records) (hashtable-copy statistics #f)) -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/REPL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | /** 20 | * Correspoding to the library (scheme repl) in Scheme 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class REPL extends NativeLibrary{ 24 | public static final REPL INSTANCE=new REPL(); 25 | private REPL(){ 26 | super("scheme","repl"); 27 | } 28 | @Override 29 | protected void init(Library lib){ 30 | addNativeProcedure("interaction-environment",(o)->Utility.getInteractiveEnvironment()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/UncaughtExceptionError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | 19 | /** 20 | * Being thrown when a exception is no caught 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class UncaughtExceptionError extends Error{ 24 | /** 25 | * Wrap a Exception 26 | * @param cause 27 | */ 28 | public UncaughtExceptionError(RuntimeException cause){ 29 | super(cause); 30 | } 31 | @Override 32 | public synchronized RuntimeException getCause(){ 33 | return (RuntimeException)super.getCause(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.github.chungkwong 8 | jschememin 9 | 1.0-SNAPSHOT 10 | jar 11 | 12 | jschememin 13 | A implementation of the Scheme language R7RS 14 | http://github.com/chungkwong/jschememin 15 | 16 | 17 | 18 | GNU GENERAL PUBLIC LICENSE, Version 3 19 | https://www.gnu.org/licenses/gpl.txt 20 | 21 | 22 | 23 | 24 | 25 | Chan Chung Kwong 26 | 1m02math@126.com 27 | SYSU 28 | http://www.sysu.edu.cn 29 | 30 | 31 | 32 | 33 | scm:git:https://github.com/chungkwong/JSchemeMin.git 34 | scm:git:ssh://github.com:chungkwong/JSchemeMin.git 35 | http://github.com/chungkwong/jschememin/tree/master 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmEndOfFileObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | 19 | /** 20 | * Represents the end-of-file object in Scheme 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class ScmEndOfFileObject extends ScmObject{ 24 | /** 25 | * The object 26 | */ 27 | public static final ScmEndOfFileObject INSTANCE=new ScmEndOfFileObject(); 28 | private ScmEndOfFileObject(){ 29 | } 30 | @Override 31 | public String toExternalRepresentation(){ 32 | return "eof-object"; 33 | } 34 | @Override 35 | public boolean isSelfevaluating(){ 36 | return false; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/SyntaxException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package com.github.chungkwong.jschememin; 19 | /** 20 | * Syntax exception when parsing script 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class SyntaxException extends RuntimeException{ 24 | /** 25 | * Creates a new instance of SyntaxException without detail message. 26 | */ 27 | public SyntaxException() { 28 | } 29 | /** 30 | * Constructs an instance of SyntaxException with the specified detail message. 31 | * @param msg the detail message. 32 | */ 33 | public SyntaxException(String msg) { 34 | super(msg); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/SimpleToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | import java.util.*; 17 | /** 18 | * Standard tokens 19 | * @author kwong 20 | */ 21 | public final class SimpleToken implements Token{ 22 | private final String id; 23 | private SimpleToken(String id){ 24 | this.id=id; 25 | } 26 | /** 27 | * build a token 28 | * @param id the text 29 | * @return the token 30 | */ 31 | public static SimpleToken getToken(String id){ 32 | return new SimpleToken(id); 33 | } 34 | @Override 35 | public String toString(){ 36 | return id; 37 | } 38 | @Override 39 | public boolean equals(Object obj){ 40 | return obj instanceof SimpleToken&&((SimpleToken)obj).id.equals(id); 41 | } 42 | @Override 43 | public int hashCode(){ 44 | return Objects.hashCode(this.id); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/lazy.scm: -------------------------------------------------------------------------------- 1 | (define-library (scheme lazy) 2 | (import (scheme base)) 3 | (export delay-force delay make-promise force promise?) 4 | (begin 5 | (define make-promise-aux 6 | (lambda (done? proc) 7 | (list (cons done? proc)))) 8 | 9 | (define-syntax delay-force 10 | (syntax-rules () 11 | ((delay-force expression) 12 | (make-promise-aux #f (lambda () expression))))) 13 | 14 | (define-syntax delay 15 | (syntax-rules () 16 | ((delay expression) 17 | (delay-force (make-promise-aux #t expression))))) 18 | 19 | (define make-promise 20 | (lambda (obj) 21 | (list (cons #t obj) obj))) 22 | 23 | (define (force promise) 24 | (if (promise-done? promise) 25 | (promise-value promise) 26 | (let ((promise* ((promise-value promise)))) 27 | (unless (promise-done? promise) 28 | (promise-update! promise* promise)) 29 | (force promise)))) 30 | 31 | (define promise? 32 | (lambda (x) (and (pair? x) (pair? (car x))))) 33 | 34 | (define promise-done? 35 | (lambda (x) (car (car x)))) 36 | (define promise-value 37 | (lambda (x) (cdr (car x)))) 38 | (define promise-update! 39 | (lambda (new old) 40 | (set-car! (car old) (promise-done? new)) 41 | (set-cdr! (car old) (promise-value new)) 42 | (set-car! new (car old)))))) -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Quote.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive quote in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Quote extends BasicConstruct implements Primitive{ 25 | public static final Quote INSTANCE=new Quote(); 26 | private Quote(){ 27 | super(new ScmSymbol("quote")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil expr){ 31 | cont.ret(ScmList.first(expr)); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: all clean cleaner checkindex 3 | 4 | all: r7rs.pdf overview.pdf 5 | 6 | clean: 7 | rm -f *~ 8 | 9 | cleaner: clean 10 | rm -f *.pdf *.aux *.log *.idx *.toc *.out 11 | 12 | DIFF_SOURCES=basic.tex derive.tex example.tex expr.tex \ 13 | lex.tex procs.tex prog.tex struct.tex 14 | 15 | SOURCES=r7rs.tex $(DIFF_SOURCES) intro.tex \ 16 | bib.tex syn.tex commands.tex first.tex notes.tex \ 17 | repository.tex index.tex sem.tex stdmod-raw.tex \ 18 | features.tex 19 | 20 | # index.tex: r7rs.idx 21 | # csi index.sch -e '(run)' 22 | 23 | stdmod.tex: stdmod-raw.tex 24 | ./genstdmod.pl < $< > $@ 25 | 26 | checkindex: stdmod-raw.tex index.tex 27 | ./checkindex.sh 28 | 29 | intro-ebook.tex: intro.tex 30 | sed 's/\\clearextrapart{\(.*\)}/\1/g' $< > $@ 31 | 32 | r7rs.pdf: $(SOURCES) stdmod.tex 33 | xelatex $< 34 | xelatex $< 35 | 36 | overview.pdf: overview.tex overview-body.tex 37 | xelatex $< 38 | xelatex $< 39 | 40 | r7rs-ebook.pdf: r7rs-ebook.tex intro-ebook.tex $(SOURCES) stdmod.tex 41 | xelatex $< 42 | xelatex $< 43 | 44 | r5diff/%.tex: %.tex 45 | hg cat -r 1 $< > r5diff/old-$< 46 | latexdiff --type=UNDERLINE --subtype=SAFE r5diff/old-$< $< | \ 47 | perl -pe 's/\\section{\\DIF(add|del){([^{}]*)}}/\\section{\2}/; s/}\\ev \\DIFadd{/\\ev/' | \ 48 | perl -pe 'BEGIN{undef $$/} s/\\ev([^%{]*)(%.*)?\n}/} \\ev \1\n/g' > $@ 49 | rm -f r5diff/old-$< 50 | 51 | r5diff/r7rs.pdf: $(DIFF_SOURCES:%=r5diff/%) 52 | cd r5diff && $(MAKE) r7rs.pdf 53 | -------------------------------------------------------------------------------- /doc/genstdmod.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use warnings; 4 | use strict; 5 | 6 | use constant COLUMNS => 2; 7 | use constant COLUMN_WIDTH => 24; 8 | 9 | my $list; 10 | 11 | my $list_only; 12 | if ($#ARGV >= 0 and $ARGV[0] =~ /^--?l(ist([-_]?only)?)?$/i) { 13 | shift; 14 | $list_only = 1; 15 | } 16 | 17 | while (<>) { 18 | if (/^\.(.*)/) { 19 | $list .= "$1\n"; 20 | } else { 21 | if (length($list)) { 22 | $list = "" unless defined($list); 23 | if ($list_only) { 24 | print "$_\n" for sort split(/\s+/, $list); 25 | } else { 26 | my $columnated; 27 | my $column = 0; 28 | my $space = ""; 29 | for my $id (sort split(/\s+/, $list)) { 30 | my $new_column = $column + 1 + int(length($id) / COLUMN_WIDTH); 31 | if ($new_column > COLUMNS) { 32 | $columnated .= "\n"; 33 | $new_column -= $column; 34 | $column = 0; 35 | $space = ""; 36 | } 37 | $columnated .= $space . $id; 38 | $space = " " x (($new_column-$column)*COLUMN_WIDTH - length($id)); 39 | $space .= " " x ($new_column-$column-1); 40 | $column = $new_column; 41 | } 42 | $columnated =~ s/_/\\_/g; 43 | $columnated =~ s/\? /\?\\ /g; 44 | $columnated =~ s/((?:\\.|\S)+)/{\\cf $1}/g; 45 | print "$columnated\n"; 46 | undef $list; 47 | } 48 | } 49 | print unless $list_only; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Eval.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive eval in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Eval extends BasicConstruct{ 25 | public static final Eval INSTANCE=new Eval(); 26 | private Eval(){ 27 | super(new ScmSymbol("eval")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | cont.callTail(ExpressionEvaluator.INSTANCE,ScmList.toList(ScmList.first(param)),(SchemeEnvironment)ScmList.second(param)); 32 | } 33 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/SyntaxRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive syntax-rules in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class SyntaxRule extends BasicConstruct implements Primitive{ 25 | public static final SyntaxRule INSTANCE=new SyntaxRule(); 26 | private SyntaxRule(){ 27 | super(new ScmSymbol("syntax-rules")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | cont.ret(new ScmSyntaxRules((ScmPair)param,env)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Lambda.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive lambda in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Lambda extends BasicConstruct implements Primitive{ 25 | public static final Lambda INSTANCE=new Lambda(); 26 | private Lambda(){ 27 | super(new ScmSymbol("lambda")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil expr){ 31 | ScmPair list=(ScmPair)expr; 32 | cont.ret(new ScmProcedure(list.getCar(),(ScmPair)list.getCdr(),env)); 33 | } 34 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/BasicConstruct.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | /** 20 | * The base class for primitives 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public abstract class BasicConstruct extends Evaluable{ 24 | private final ScmSymbol keyword; 25 | /** 26 | * Construct a BasicConstruct 27 | * @param keyword 28 | */ 29 | protected BasicConstruct(ScmSymbol keyword){ 30 | this.keyword=keyword; 31 | } 32 | /** 33 | * Get the keyword 34 | * @return 35 | */ 36 | public ScmSymbol getKeyword(){ 37 | return keyword; 38 | } 39 | @Override 40 | public String toExternalRepresentation(){ 41 | return keyword.getValue(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /doc/features.tex: -------------------------------------------------------------------------------- 1 | \chapter{Standard Feature Identifiers} 2 | \label{stdfeatures} 3 | 4 | An implementation may provide any or all of the feature identifiers 5 | listed below for use by {\cf cond-expand} and {\cf features}, 6 | but must not provide a feature identifier if it does not 7 | provide the corresponding feature. 8 | 9 | \label{standard_features} 10 | 11 | \feature{r7rs}{All \rsevenrs\ Scheme implementations have this feature.} 12 | \feature{exact-closed}{All algebraic operations except {\cf /} produce 13 | exact values given exact inputs.} 14 | \feature{exact-complex}{Exact complex numbers are provided.} 15 | \feature{ieee-float}{Inexact numbers are IEEE 754 binary floating point 16 | values.} 17 | \feature{full-unicode}{All Unicode characters present in Unicode version 6.0 are supported as Scheme characters.} 18 | \feature{ratios}{{\cf /} with exact arguments produces an exact result 19 | when the divisor is nonzero.} 20 | \feature{posix}{This implementation is running on a POSIX 21 | system.} 22 | \feature{windows}{This implementation is running on Windows.} 23 | \feature{unix, darwin, gnu-linux, bsd, freebsd, solaris, ...}{Operating 24 | system flags (perhaps more than one).} 25 | \feature{i386, x86-64, ppc, sparc, jvm, clr, llvm, ...}{CPU architecture flags.} 26 | \feature{ilp32, lp64, ilp64, ...}{C memory model flags.} 27 | \feature{big-endian, little-endian}{Byte order flags.} 28 | \feature{\hyper{name}}{The name of this implementation.} 29 | \feature{\hyper{name-version}}{The name and version of this 30 | implementation.} 31 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Read.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.car; 20 | import com.github.chungkwong.jschememin.type.*; 21 | /** 22 | * Correspoding to the library (scheme read) in Scheme 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class Read extends NativeLibrary{ 26 | public static final Read INSTANCE=new Read(); 27 | private Read(){ 28 | super("scheme","read"); 29 | } 30 | @Override 31 | protected void init(Library lib){ 32 | addNativeProcedure("read",new NativeProcedureDefault((o)->new Parser(new Lex(((ScmTextualInputPort)car(o)).getReader())).nextDatum(), 33 | (o)->ScmPort.CURRENT_INPUT)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Time.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the library (scheme time) in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Time extends NativeLibrary{ 25 | public static final Time INSTANCE=new Time(); 26 | private Time(){ 27 | super("scheme","time"); 28 | } 29 | @Override 30 | protected void init(Library lib){ 31 | addNativeProcedure("current-second",(o)->new ScmInteger(System.currentTimeMillis()/1000)); 32 | addNativeProcedure("current-jiffy",(o)->new ScmInteger(System.nanoTime())); 33 | addNativeProcedure("jiffies-per-second",(o)->new ScmInteger(1000000000)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/CallWithValues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive call-with-values in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class CallWithValues extends BasicConstruct{ 25 | public static final CallWithValues INSTANCE=new CallWithValues(); 26 | private CallWithValues(){ 27 | super(new ScmSymbol("call-with-values")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | cont.callTail((Evaluable)ScmList.second(param),ScmNil.NIL,env); 32 | cont.call((Evaluable)ScmList.first(param),null,ScmNil.NIL,env); 33 | } 34 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Eval.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.primitive.*; 20 | /** 21 | * Correspoding to the library (scheme eval) in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Eval extends NativeLibrary{ 25 | public static final Eval INSTANCE=new Eval(); 26 | private Eval(){ 27 | super("scheme","eval"); 28 | } 29 | @Override 30 | protected void init(Library lib){ 31 | addNativeProcedure("environment",(o)->Import.INSTANCE.importLibraries(new SchemeEnvironment(false),o)); 32 | addPrimitiveType(com.github.chungkwong.jschememin.primitive.Eval.INSTANCE); 33 | //addNativeProcedure("eval",(o)->new Evaluator((Environment)cadr(o)).eval(car(o))); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin.type; 16 | /** 17 | * Represents objects in scheme 18 | * @author kwong 19 | */ 20 | public abstract class ScmObject{ 21 | /** 22 | * Get the external representation of the object 23 | * @return the String 24 | */ 25 | public abstract String toExternalRepresentation(); 26 | /** 27 | * Check if the object is self-evaluating 28 | * @return 29 | */ 30 | public abstract boolean isSelfevaluating(); 31 | @Override 32 | public String toString(){ 33 | return toExternalRepresentation(); 34 | } 35 | /** 36 | * Corresponding to the procedure eqv? in Scheme 37 | * @param obj 38 | * @return 39 | */ 40 | public boolean equalsValue(ScmObject obj){ 41 | return equals(obj); 42 | } 43 | /** 44 | * Corresponding to the procedure eq? in Scheme 45 | * @param obj 46 | * @return 47 | */ 48 | public boolean equalsStrict(ScmObject obj){ 49 | return equalsValue(obj); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/WithExceptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive with-exception-handler in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class WithExceptionHandler extends BasicConstruct{ 25 | public static final WithExceptionHandler INSTANCE=new WithExceptionHandler(); 26 | private WithExceptionHandler(){ 27 | super(new ScmSymbol("with-exception-handler")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | if(pointer==null){ 32 | cont.replaceCurrent(this); 33 | cont.call((Evaluable)ScmList.second(param),ScmList.first(param),ScmNil.NIL,env); 34 | }else 35 | cont.ret(param); 36 | } 37 | } -------------------------------------------------------------------------------- /test/com/github/chungkwong/jschememin/EmbedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Chan Chung Kwong 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.util.function.*; 20 | import javax.script.*; 21 | import org.junit.*; 22 | /** 23 | * 24 | * @author Chan Chung Kwong 25 | */ 26 | public class EmbedTest{ 27 | public EmbedTest(){ 28 | } 29 | @Test 30 | public void testJavaFunction() throws ScriptException{ 31 | ScriptEngine engine=EvaluatorFactory.INSTANCE.getScriptEngine(); 32 | SimpleBindings bindings=new SimpleBindings(); 33 | Function f=new Function(){ 34 | @Override 35 | public String apply(String t){ 36 | return t.toUpperCase(); 37 | } 38 | }; 39 | bindings.put("up",f); 40 | bindings.put("str","hello"); 41 | engine.setBindings(bindings,ScriptContext.GLOBAL_SCOPE); 42 | Assert.assertEquals(engine.eval("(up \"heLlo\")"),new ScmString("HELLO")); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Assignment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive set! in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Assignment extends BasicConstruct implements Primitive{ 25 | public static final Assignment INSTANCE=new Assignment(); 26 | private Assignment(){ 27 | super(new ScmSymbol("set!")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil expr){ 31 | if(pointer==null){ 32 | cont.replaceCurrent(this); 33 | cont.call(ExpressionEvaluator.INSTANCE,(ScmSymbol)ScmList.first(expr),ScmList.second(expr),env); 34 | }else{ 35 | env.set((ScmSymbol)pointer,ScmList.first(expr)); 36 | cont.ret(expr); 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/RaiseContinuable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive raise-continuable in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class RaiseContinuable extends BasicConstruct{ 25 | public static final RaiseContinuable INSTANCE=new RaiseContinuable(); 26 | private RaiseContinuable(){ 27 | super(new ScmSymbol("raise-continuable")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | ScmPair handler=cont.getErrorHandler(); 32 | if(handler==null) 33 | throw new UncaughtExceptionError(ScmError.toException(ScmList.first(param))); 34 | cont.callTail((Evaluable)handler.getCar(),param,(SchemeEnvironment)handler.getCdr()); 35 | } 36 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/cxr.scm: -------------------------------------------------------------------------------- 1 | (define-library (scheme cxr) 2 | (import (scheme base)) 3 | (export caaaar caaadr caaar caadar caaddr caadr cadaar cadadr cadar caddar cadddr caddr cdaaar 4 | cdaadr cdaar cdadar cdaddr cdadr cddaar cddadr cddar cdddar cddddr cdddr) 5 | (begin 6 | (define caaaar (lambda (x) (car (car (car (car x)))))) 7 | (define caaar (lambda (x) (car (car (car x))))) 8 | (define caaddr (lambda (x) (car (car (cdr (cdr x)))))) 9 | (define cadaar (lambda (x) (car (cdr (car (car x)))))) 10 | (define cadar (lambda (x) (car (cdr (car x))))) 11 | (define cadddr (lambda (x) (car (cdr (cdr (cdr x)))))) 12 | (define cdaaar (lambda (x) (cdr (car (car (car x)))))) 13 | (define cdaar (lambda (x) (cdr (car (car x))))) 14 | (define cdaddr (lambda (x) (cdr (car (cdr (cdr x)))))) 15 | (define cddaar (lambda (x) (cdr (cdr (car (car x)))))) 16 | (define cddar (lambda (x) (cdr (cdr (car x))))) 17 | (define cddddr (lambda (x) (cdr (cdr (cdr (cdr x)))))) 18 | (define caaadr (lambda (x) (car (car (car (cdr x)))))) 19 | (define caadar (lambda (x) (car (car (cdr (car x)))))) 20 | (define caadr (lambda (x) (car (car (cdr x))))) 21 | (define cadadr (lambda (x) (car (cdr (car (cdr x)))))) 22 | (define caddar (lambda (x) (car (cdr (cdr (car x)))))) 23 | (define caddr (lambda (x) (car (cdr (cdr x))))) 24 | (define cdaadr (lambda (x) (cdr (car (car (cdr x)))))) 25 | (define cdadar (lambda (x) (cdr (car (cdr (car x)))))) 26 | (define cdadr (lambda (x) (cdr (car (cdr x))))) 27 | (define cddadr (lambda (x) (cdr (cdr (car (cdr x)))))) 28 | (define cdddar (lambda (x) (cdr (cdr (cdr (car x)))))) 29 | (define cdddr (lambda (x) (cdr (cdr (cdr x))))))) -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Apply.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive apply in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Apply extends BasicConstruct{ 25 | public static final Apply INSTANCE=new Apply(); 26 | private Apply(){ 27 | super(new ScmSymbol("apply")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | ScmListBuilder buf=new ScmListBuilder(); 32 | Evaluable proc=(Evaluable)ScmList.first(param); 33 | ScmPair curr=(ScmPair)((ScmPair)param).getCdr(); 34 | for(;curr.getCdr() instanceof ScmPair;curr=(ScmPair)curr.getCdr()){ 35 | buf.add(curr.getCar()); 36 | } 37 | ScmList.forEach(curr.getCar(),(o)->buf.add(o)); 38 | cont.callTail(proc,(ScmPairOrNil)buf.toList(),env); 39 | } 40 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/NativeEvaluable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Represents native procedures 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class NativeEvaluable extends Evaluable{ 25 | private final NativeProcedure proc; 26 | /** 27 | * Wrap a NativeProcedure 28 | * @param proc 29 | */ 30 | public NativeEvaluable(NativeProcedure proc){ 31 | this.proc=proc; 32 | } 33 | @Override 34 | public String toExternalRepresentation(){ 35 | return this.getClass().getCanonicalName(); 36 | } 37 | @Override 38 | public boolean isSelfevaluating(){ 39 | return false; 40 | } 41 | @Override 42 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 43 | try{ 44 | cont.ret(proc.call(param)); 45 | }catch(Exception ex){ 46 | throw ScmError.toRuntimeException(ex); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/DatumLabel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015,2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | import com.github.chungkwong.jschememin.type.*; 17 | import java.util.*; 18 | /** 19 | * Represents labels for datum 20 | * @author kwong 21 | */ 22 | public abstract class DatumLabel extends ScmObject implements Token{ 23 | private final String label; 24 | /** 25 | * Create a label 26 | * @param label the label name 27 | */ 28 | protected DatumLabel(String label){ 29 | this.label=label; 30 | } 31 | /** 32 | * Get label name 33 | * @return 34 | */ 35 | public String getLabel(){ 36 | return label; 37 | } 38 | @Override 39 | public boolean equals(Object obj){ 40 | return obj instanceof DatumLabel&&((DatumLabel)obj).label.equals(label); 41 | } 42 | @Override 43 | public int hashCode(){ 44 | int hash=7; 45 | hash=97*hash+Objects.hashCode(getLabel()); 46 | return hash; 47 | } 48 | @Override 49 | public String toExternalRepresentation(){ 50 | throw new UnsupportedOperationException("Not supported yet."); 51 | } 52 | @Override 53 | public boolean isSelfevaluating(){ 54 | throw new UnsupportedOperationException("Not supported yet."); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Feature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | import com.github.chungkwong.jschememin.type.*; 17 | import java.util.*; 18 | /** 19 | * 20 | * @author Chan Chung Kwong <1m02math@126.com> 21 | */ 22 | public class Feature{ 23 | private static final HashSet FEATURES=new HashSet<>(); 24 | static{ 25 | FEATURES.add("r7rs"); 26 | FEATURES.add("exact-closed"); 27 | FEATURES.add("exact-complex"); 28 | //FEATURES.add("ieee-float"); 29 | FEATURES.add("full-unicode"); 30 | FEATURES.add("ratios"); 31 | FEATURES.add("jvm"); 32 | FEATURES.add("jschememin"); 33 | FEATURES.add("jschememin-0.0.1"); 34 | FEATURES.add(System.getProperty("os.arch")); 35 | FEATURES.add(System.getProperty("os.name")); 36 | } 37 | /** 38 | * Check if a feature is presented 39 | * @param feature 40 | * @return 41 | */ 42 | public static boolean contains(String feature){ 43 | return FEATURES.contains(feature); 44 | } 45 | /** 46 | * Get all features presented 47 | * @return 48 | */ 49 | public static ScmPairOrNil getAll(){ 50 | return ScmList.toList(FEATURES.stream().map((feature)->new ScmSymbol(feature)).toArray(ScmObject[]::new)); 51 | } 52 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/NativeEvaluableMulti.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Represents native procedures that may return many values 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class NativeEvaluableMulti extends Evaluable{ 25 | private final NativeProcedure proc; 26 | /** 27 | * Wrap a NativeProcedure 28 | * @param proc 29 | */ 30 | public NativeEvaluableMulti(NativeProcedure proc){ 31 | this.proc=proc; 32 | } 33 | @Override 34 | public String toExternalRepresentation(){ 35 | return this.getClass().getCanonicalName(); 36 | } 37 | @Override 38 | public boolean isSelfevaluating(){ 39 | return false; 40 | } 41 | @Override 42 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 43 | try{ 44 | cont.ret((ScmPairOrNil)proc.call(param)); 45 | }catch(Exception ex){ 46 | throw ScmError.toRuntimeException(ex); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Raise.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive raise in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Raise extends BasicConstruct{ 25 | public static final Raise INSTANCE=new Raise(); 26 | private Raise(){ 27 | super(new ScmSymbol("raise")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | cont.removeUntilErrorHandler(); 32 | if(cont.hasNext()){ 33 | if(pointer!=null){ 34 | param=(ScmPairOrNil)pointer; 35 | } 36 | ScmObject handler=(ScmObject)cont.getCurrentPointer(); 37 | SchemeEnvironment e=cont.getCurrentEnvironment(); 38 | cont.callTail(this,param,env); 39 | cont.call((Evaluable)handler,param,param,e); 40 | }else{ 41 | throw new UncaughtExceptionError(ScmError.toException(ScmList.first(param))); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmUniqueSymbol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | 19 | /** 20 | * Represents symbols that is difference to all existing ones 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class ScmUniqueSymbol extends ScmSymbol{ 24 | private static int seq=0; 25 | private final ScmSymbol org; 26 | /** 27 | * Construcr a unique symbol 28 | * @param org the prefered name 29 | */ 30 | public ScmUniqueSymbol(ScmSymbol org){ 31 | super(Integer.toString(seq++)); 32 | this.org=toLiteral(org); 33 | } 34 | /** 35 | * Get the prefered name 36 | * @return 37 | */ 38 | public ScmSymbol getOrigin(){ 39 | return org; 40 | } 41 | /** 42 | * Get prefered name or itself 43 | * @param id 44 | * @return 45 | */ 46 | public static ScmSymbol toLiteral(ScmSymbol id){ 47 | return id instanceof ScmUniqueSymbol?((ScmUniqueSymbol)id).getOrigin():id; 48 | } 49 | @Override 50 | public String toString(){ 51 | return org.toString(); //To change body of generated methods, choose Tools | Templates. 52 | } 53 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Evaluable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | /** 20 | * Represents expression types 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public abstract class Evaluable extends ScmObject{ 24 | @Override 25 | public boolean isSelfevaluating(){ 26 | return false; 27 | } 28 | /** 29 | * To be called when such exprssion is evaluated 30 | * @param env the environment where the exprssion is evaluated 31 | * @param cont the execution stack 32 | * @param pointer saved at last call 33 | * @param param parameters given to the type 34 | */ 35 | public abstract void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param); 36 | /** 37 | * Call and get the result in a new stack 38 | * @param param 39 | * @return 40 | */ 41 | public ScmObject call(ScmPairOrNil param){ 42 | Continuation cont=new Continuation(); 43 | cont.callInit(this,param,null); 44 | while(cont.hasNext()) 45 | cont.evalNext(); 46 | return cont.getCurrentValue(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmBoolean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin.type; 16 | import com.github.chungkwong.jschememin.*; 17 | public final class ScmBoolean extends ScmObject implements Token{ 18 | /** 19 | * True 20 | */ 21 | public static final ScmBoolean TRUE=new ScmBoolean(true); 22 | /** 23 | * False 24 | */ 25 | public static final ScmBoolean FALSE=new ScmBoolean(false); 26 | private final boolean val; 27 | /** 28 | * Wrap a boolean 29 | * @param val the value 30 | */ 31 | private ScmBoolean(boolean val){ 32 | this.val=val; 33 | } 34 | /** 35 | * Convert to boolean 36 | * @return the boolean 37 | */ 38 | public boolean isTrue(){ 39 | return val; 40 | } 41 | @Override 42 | public boolean equals(Object obj){ 43 | return this==obj; 44 | } 45 | @Override 46 | public int hashCode(){ 47 | return this.val?1:0; 48 | } 49 | @Override 50 | public String toExternalRepresentation(){ 51 | return val?"#t":"#f"; 52 | } 53 | @Override 54 | public boolean isSelfevaluating(){ 55 | return true; 56 | } 57 | /** 58 | * Convert from a boolean 59 | * @param b the boolean 60 | * @return the Scheme boolean 61 | */ 62 | public static ScmBoolean valueOf(boolean b){ 63 | return b?ScmBoolean.TRUE:ScmBoolean.FALSE; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmSymbol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin.type; 16 | import com.github.chungkwong.jschememin.*; 17 | import java.util.*; 18 | /** 19 | * Represents the type symbol in Scheme 20 | * @author kwong 21 | */ 22 | public class ScmSymbol extends ScmObject implements Token{ 23 | private final String id; 24 | /** 25 | * Make a symbol 26 | * @param id the name of the symbol 27 | */ 28 | public ScmSymbol(String id){ 29 | this.id=id; 30 | } 31 | /** 32 | * Get the name of the symbol 33 | * @return 34 | */ 35 | public String getValue(){ 36 | return id; 37 | } 38 | @Override 39 | public boolean equals(Object obj){ 40 | return obj!=null&&getClass().equals(obj.getClass())&&((ScmSymbol)obj).id.equals(id); 41 | } 42 | @Override 43 | public int hashCode(){ 44 | int hash=7; 45 | hash=97*hash+Objects.hashCode(this.id); 46 | return hash; 47 | } 48 | @Override 49 | public String toExternalRepresentation(){ 50 | StringBuilder buf=new StringBuilder(); 51 | buf.append('|'); 52 | id.codePoints().forEach((c)->{ 53 | if(c=='|'||c=='\\') 54 | buf.append('\\'); 55 | buf.appendCodePoint(c); 56 | }); 57 | buf.append('|'); 58 | return buf.toString(); 59 | } 60 | @Override 61 | public boolean isSelfevaluating(){ 62 | return false; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /test/com/github/chungkwong/jschememin/SchemeAssert.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.io.*; 20 | import org.junit.*; 21 | /** 22 | * 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class SchemeAssert{ 26 | public static void assertExpressionValue(String expr,String result){ 27 | ScmObject gotval=new Evaluator(true).eval(new Parser(expr).nextDatum()); 28 | ScmObject expectval=new Evaluator(true).eval(new Parser(result).nextDatum()); 29 | Assert.assertEquals(gotval,expectval); 30 | } 31 | public static void assertStandardOutput(String expr,String result){ 32 | StringWriter out=new StringWriter(); 33 | ScmPort.CURRENT_OUTPUT=new ScmTextualOutputPort(out); 34 | try{ 35 | new Evaluator(true).eval(new Parser(expr).nextDatum()); 36 | }catch(RuntimeException ex){ 37 | 38 | } 39 | Assert.assertEquals(out.toString(),result); 40 | } 41 | public static void expectException(String expr){ 42 | try{ 43 | new Evaluator(true).eval(new Parser(expr).nextDatum()); 44 | Assert.assertTrue(false); 45 | }catch(Throwable ex){ 46 | 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/If.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive if in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class If extends BasicConstruct implements Primitive{ 25 | public static final If INSTANCE=new If(); 26 | private If(){ 27 | super(new ScmSymbol("if")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil expr){ 31 | if(pointer==null){ 32 | ScmPair list=(ScmPair)expr; 33 | cont.replaceCurrent(this); 34 | cont.call(ExpressionEvaluator.INSTANCE,(ScmPair)list.getCdr(),list.getCar(),env); 35 | }else{ 36 | ScmPair list=(ScmPair)pointer; 37 | if(ScmList.first(expr)==ScmBoolean.FALSE){ 38 | if(list.getCdr() instanceof ScmPair) 39 | cont.callTail(ExpressionEvaluator.INSTANCE,list.getCadr(),env); 40 | else 41 | cont.ret(new ScmSymbol("unspecified")); 42 | }else{ 43 | cont.callTail(ExpressionEvaluator.INSTANCE,list.getCar(),env); 44 | } 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmPort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | import java.io.*; 19 | /** 20 | * 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public abstract class ScmPort extends ScmObject{ 24 | /** 25 | * current-input-port in Scheme 26 | */ 27 | public static ScmPort CURRENT_INPUT=new ScmTextualInputPort(new InputStreamReader(System.in)); 28 | /** 29 | * current-output-port in Scheme 30 | */ 31 | public static ScmPort CURRENT_OUTPUT=new ScmTextualOutputPort(new OutputStreamWriter(System.out)); 32 | /** 33 | * The current error port 34 | */ 35 | public static ScmPort CURRENT_ERROR=new ScmTextualOutputPort(new OutputStreamWriter(System.err)); 36 | private boolean closed=false; 37 | @Override 38 | public boolean isSelfevaluating(){ 39 | return false; 40 | } 41 | /** 42 | * Corresponding to the procedure close-port in Scheme 43 | * @return 44 | * @throws IOException 45 | */ 46 | public ScmPort close()throws IOException{ 47 | closed=true; 48 | return this; 49 | } 50 | /** 51 | * Check if the port is closed 52 | * @return 53 | */ 54 | public boolean isClosed(){ 55 | return closed; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/DefineValues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive define-values in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class DefineValues extends BasicConstruct implements Primitive{ 25 | public static final DefineValues INSTANCE=new DefineValues(); 26 | private DefineValues(){ 27 | super(new ScmSymbol("define-values")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil expr){ 31 | if(pointer==null){ 32 | cont.replaceCurrent(this); 33 | cont.call(ExpressionEvaluator.INSTANCE,ScmList.first(expr),(ScmPairOrNil)((ScmPair)expr).getCdr(),env); 34 | }else{ 35 | ScmObject expr2=expr; 36 | while(pointer instanceof ScmPair){ 37 | env.add((ScmSymbol)((ScmPair)pointer).getCar(),((ScmPair)expr2).getCar()); 38 | pointer=((ScmPair)pointer).getCdr(); 39 | expr2=(ScmPairOrNil)((ScmPair)expr2).getCdr(); 40 | } 41 | if(pointer instanceof ScmSymbol) 42 | env.add((ScmSymbol)pointer,expr2); 43 | cont.ret((ScmObject)expr); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Complex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.cadr; 20 | import static com.github.chungkwong.jschememin.lib.Utility.car; 21 | import com.github.chungkwong.jschememin.type.*; 22 | /** 23 | * Correspoding to the library (scheme complex) in Scheme 24 | * @author Chan Chung Kwong <1m02math@126.com> 25 | */ 26 | public class Complex extends NativeLibrary{ 27 | public static final Complex INSTANCE=new Complex(); 28 | private Complex(){ 29 | super("scheme","complex"); 30 | } 31 | @Override 32 | protected void init(Library lib){ 33 | addNativeProcedure("imag-part",(o)->((ScmComplex)car(o)).getImag()); 34 | addNativeProcedure("real-part",(o)->((ScmComplex)car(o)).getReal()); 35 | addNativeProcedure("angle",(o)->((ScmComplex)car(o)).getAngle()); 36 | addNativeProcedure("magnitude",(o)->((ScmComplex)car(o)).getMagnitude()); 37 | addNativeProcedure("make-rectangular",(o)->new ScmComplexRectangular( 38 | ((ScmComplex)car(o)).toScmReal(),((ScmComplex)cadr(o)).toScmReal())); 39 | addNativeProcedure("make-polar",(o)->new ScmComplexPolar( 40 | ((ScmComplex)car(o)).toScmReal(),((ScmComplex)cadr(o)).toScmReal())); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/NativeProcedureDefault.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.util.function.*; 20 | /** 21 | * NativeProcedure with default arguments 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class NativeProcedureDefault implements NativeProcedure{ 25 | private final NativeProcedure proc; 26 | private final Function[] def; 27 | /** 28 | * 29 | * @param proc the NativeProcedure 30 | * @param def the functions being used to generate default argument 31 | */ 32 | public NativeProcedureDefault(NativeProcedure proc,Function... def){ 33 | this.proc=proc; 34 | this.def=def; 35 | } 36 | @Override 37 | public ScmObject call(ScmObject param) throws Exception{ 38 | if(ScmList.getLength(param) 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive call/cc in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class CallWithCurrentContinuation extends BasicConstruct{ 25 | public static final CallWithCurrentContinuation INSTANCE=new CallWithCurrentContinuation(); 26 | private CallWithCurrentContinuation(){ 27 | super(new ScmSymbol("call-with-current-continuation")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | cont.callTail((Evaluable)ScmList.first(param),ScmList.toList(getRollbackProcedure(cont.getCopy())),env); 32 | } 33 | static final ScmObject getRollbackProcedure(Continuation checkpoint){ 34 | return new Evaluable(){ 35 | @Override 36 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 37 | cont.reset(checkpoint); 38 | cont.ret((ScmPairOrNil)param); 39 | } 40 | @Override 41 | public String toExternalRepresentation(){ 42 | return "roll-back-procedure"; 43 | } 44 | }; 45 | } 46 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin; 16 | import com.github.chungkwong.jschememin.type.*; 17 | import java.io.*; 18 | import java.util.*; 19 | /** 20 | * 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class Main { 24 | /** 25 | * Command line arguments given to JSchemeMin 26 | */ 27 | public static ScmPairOrNil COMMAND_LINE; 28 | /** 29 | * Entrance to the interpreter 30 | * @param args the command line arguments 31 | */ 32 | public static void main(String[] args) { 33 | COMMAND_LINE=(ScmPairOrNil)Arrays.stream(args).map((arg)->new ScmString(arg)).collect(ScmList.COLLECTOR); 34 | if(args.length>=1&&args[0].equals("-d")){ 35 | Debugger.main(args); 36 | return; 37 | } 38 | System.out.println("JSchemeMin REPL"); 39 | Evaluator eval=new Evaluator(true); 40 | System.out.print("> "); 41 | System.out.flush(); 42 | Parser parser=new Parser(new Lex(new InputStreamReader(System.in))); 43 | while(true){ 44 | try{ 45 | ScmObject d=parser.nextDatum(); 46 | if(d==null) 47 | return; 48 | System.out.println("=> "+eval.eval(d)); 49 | }catch(RuntimeException ex){ 50 | ex.printStackTrace(); 51 | } 52 | System.out.print("> "); 53 | System.out.flush(); 54 | } 55 | } 56 | /** 57 | * Find a find 58 | * @param path the path to the file 59 | * @return 60 | */ 61 | public static File resolveFile(String path){ 62 | return new File(path).getAbsoluteFile(); 63 | } 64 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/JSchemeMin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.car; 20 | import com.github.chungkwong.jschememin.type.*; 21 | import java.lang.management.*; 22 | /** 23 | * Correspoding to the library (jschememin) in Scheme 24 | * @author Chan Chung Kwong <1m02math@126.com> 25 | */ 26 | public class JSchemeMin extends NativeLibrary{ 27 | public static final JSchemeMin INSTANCE=new JSchemeMin(); 28 | static final NativeProcedure LIBRARY_EXISTS=(o)->ScmBoolean.valueOf(LibraryManager.hasLibrary((ScmPair)car(o))); 29 | private JSchemeMin(){ 30 | super("jschememin"); 31 | } 32 | @Override 33 | protected void init(Library lib){ 34 | addNativeProcedure("library-exists?",LIBRARY_EXISTS); 35 | addNativeProcedure("thread-clock",(o)->ScmInteger.valueOf(ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime())); 36 | addNativeProcedure("memory-total",(o)->ScmInteger.valueOf(Runtime.getRuntime().totalMemory())); 37 | addNativeProcedure("memory-free",(o)->ScmInteger.valueOf(Runtime.getRuntime().freeMemory())); 38 | addDeriveFile("/com/github/chungkwong/jschememin/lib/jschememin_derive.scm", 39 | "duration","count","total-time","profile-lambda","profile-record","profile-records"); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Write.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.cadr; 20 | import static com.github.chungkwong.jschememin.lib.Utility.car; 21 | import com.github.chungkwong.jschememin.type.*; 22 | /** 23 | * Correspoding to the library (scheme write) in Scheme 24 | * @author Chan Chung Kwong <1m02math@126.com> 25 | */ 26 | public class Write extends NativeLibrary{ 27 | public static final Write INSTANCE=new Write(); 28 | private Write(){ 29 | super("scheme","write"); 30 | } 31 | @Override 32 | protected void init(Library lib){ 33 | addNativeProcedure("write",new NativeProcedureDefault((o)->((ScmTextualOutputPort)cadr(o)).write(car(o)), 34 | (o)->car(o),(o)->ScmPort.CURRENT_OUTPUT)); 35 | addNativeProcedure("write-shared",new NativeProcedureDefault((o)->((ScmTextualOutputPort)cadr(o)).writeShared(car(o)), 36 | (o)->car(o),(o)->ScmPort.CURRENT_OUTPUT)); 37 | addNativeProcedure("write-simple",new NativeProcedureDefault((o)->((ScmTextualOutputPort)cadr(o)).writeSimple(car(o)), 38 | (o)->car(o),(o)->ScmPort.CURRENT_OUTPUT)); 39 | addNativeProcedure("display",new NativeProcedureDefault((o)->((ScmTextualOutputPort)cadr(o)).display(car(o)), 40 | (o)->car(o),(o)->ScmPort.CURRENT_OUTPUT)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/SimpleLibrary.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | import java.io.*; 21 | import java.util.*; 22 | import java.util.logging.*; 23 | /** 24 | * Loder for Scheme library mainly written in Scheme 25 | * @author Chan Chung Kwong <1m02math@126.com> 26 | */ 27 | public class SimpleLibrary implements LibraryLoader{ 28 | private final ScmPair name; 29 | private final String path; 30 | private Library lib=null; 31 | /** 32 | * Construct a SimpleLibrary 33 | * @param path location of the script file 34 | * @param part the name of the library 35 | */ 36 | public SimpleLibrary(String path,String... part){ 37 | this.name=(ScmPair)Arrays.stream(part).map((n)->new ScmSymbol(n)).collect(ScmList.COLLECTOR); 38 | this.path=path; 39 | } 40 | @Override 41 | public Library getLibrary(){ 42 | if(lib==null){ 43 | try{ 44 | new Evaluator(false).eval(new Parser(new Lex(new InputStreamReader(SimpleLibrary.class.getResourceAsStream(path),"UTF-8"))).nextDatum()); 45 | }catch(UnsupportedEncodingException ex){ 46 | Logger.getGlobal().log(Level.SEVERE,null,ex); 47 | } 48 | lib=LibraryManager.getLibrary(name); 49 | } 50 | return lib; 51 | } 52 | @Override 53 | public ScmPair getName(){ 54 | return name; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /nbproject/project.properties: -------------------------------------------------------------------------------- 1 | #Sun Nov 05 13:13:57 CST 2017 2 | excludes= 3 | javac.deprecation=false 4 | build.test.results.dir=${build.dir}/test/results 5 | javac.external.vm=false 6 | run.classpath=\ 7 | ${javac.classpath}:\ 8 | ${build.classes.dir} 9 | javadoc.nonavbar=false 10 | run.test.classpath=\ 11 | ${javac.test.classpath}:\ 12 | ${build.test.classes.dir} 13 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 14 | javac.processorpath=\ 15 | ${javac.classpath} 16 | javac.target=1.8 17 | annotation.processing.processors.list= 18 | javadoc.noindex=false 19 | javadoc.additionalparam= 20 | includes=** 21 | build.classes.dir=${build.dir}/classes 22 | source.encoding=UTF-8 23 | javadoc.author=false 24 | test.src.dir=test 25 | build.dir=build 26 | build.test.classes.dir=${build.dir}/test/classes 27 | platform.active=default_platform 28 | javac.compilerargs= 29 | main.class=com.github.chungkwong.jschememin.Main 30 | dist.jar=${dist.dir}/JSchemeMin.jar 31 | javac.test.processorpath=${javac.test.classpath} 32 | javadoc.use=true 33 | dist.archive.excludes= 34 | build.sysclasspath=ignore 35 | debug.test.classpath=${run.test.classpath} 36 | dist.dir=dist 37 | build.classes.excludes=**/*.java,**/*.form 38 | javadoc.splitindex=true 39 | javadoc.encoding=${source.encoding} 40 | javac.source=1.8 41 | application.vendor=kwong 42 | junit.selected.version=4 43 | debug.classpath=${run.classpath} 44 | run.jvmargs= 45 | build.generated.dir=${build.dir}/generated 46 | jar.compress=false 47 | javac.test.classpath=\ 48 | ${javac.classpath}:\ 49 | ${build.classes.dir}:\ 50 | ${libs.junit_4.classpath}:\ 51 | ${libs.hamcrest.classpath} 52 | javadoc.private=false 53 | project.license=gpl30 54 | annotation.processing.run.all.processors=true 55 | application.title=JSchemeMin 56 | meta.inf.dir=${src.dir}/META-INF 57 | manifest.file=manifest.mf 58 | annotation.processing.enabled=true 59 | dist.javadoc.dir=${dist.dir}/javadoc 60 | src.dir=src 61 | mkdist.disabled=false 62 | endorsed.classpath= 63 | javac.classpath= 64 | annotation.processing.enabled.in.editor=false 65 | build.generated.sources.dir=${build.dir}/generated-sources 66 | javadoc.version=false 67 | javadoc.windowtitle= 68 | javadoc.notree=false 69 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/ProcessContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.car; 20 | import static com.github.chungkwong.jschememin.lib.Utility.emergencyExit; 21 | import static com.github.chungkwong.jschememin.lib.Utility.exit; 22 | import static com.github.chungkwong.jschememin.lib.Utility.getEnvironmentVariable; 23 | import static com.github.chungkwong.jschememin.lib.Utility.getEnvironmentVariables; 24 | import com.github.chungkwong.jschememin.type.*; 25 | /** 26 | * Correspoding to the library (scheme process-context) in Scheme 27 | * @author Chan Chung Kwong <1m02math@126.com> 28 | */ 29 | public class ProcessContext extends NativeLibrary{ 30 | public static final ProcessContext INSTANCE=new ProcessContext(); 31 | private ProcessContext(){ 32 | super("scheme","process-context"); 33 | } 34 | @Override 35 | protected void init(Library lib){ 36 | addNativeProcedure("command-line",(o)->Main.COMMAND_LINE); 37 | addNativeProcedure("exit",new NativeProcedureDefault((o)->{exit(o);return null;},(o)->ScmBoolean.TRUE)); 38 | addNativeProcedure("emergency-exit",new NativeProcedureDefault((o)->{emergencyExit(o);return null;},(o)->ScmBoolean.TRUE)); 39 | addNativeProcedure("get-environment-variable",(o)->getEnvironmentVariable((ScmString)car(o))); 40 | addNativeProcedure("get-environment-variables",(o)->getEnvironmentVariables()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Load.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.cadr; 20 | import static com.github.chungkwong.jschememin.lib.Utility.car; 21 | import static com.github.chungkwong.jschememin.lib.Utility.getInteractiveEnvironment; 22 | import com.github.chungkwong.jschememin.type.*; 23 | import java.io.*; 24 | /** 25 | * Correspoding to the library (scheme load) in Scheme 26 | * @author Chan Chung Kwong <1m02math@126.com> 27 | */ 28 | public class Load extends NativeLibrary{ 29 | public static final Load INSTANCE=new Load(); 30 | private static final ScmSymbol BEGIN=new ScmSymbol("begin"); 31 | private Load(){ 32 | super("scheme","load"); 33 | } 34 | @Override 35 | protected void init(Library lib){ 36 | addNativeProcedure("load",new NativeProcedureDefault((o)->load(((ScmString)car(o)).getValue(),(SchemeEnvironment)cadr(o)), 37 | (o)->car(o),(o)->getInteractiveEnvironment())); 38 | } 39 | private static ScmObject load(String filename,SchemeEnvironment env){ 40 | ScmPair content; 41 | try{ 42 | Parser parser=new Parser(new Lex(new InputStreamReader(new FileInputStream(Main.resolveFile(filename)),"UTF-8"),false)); 43 | content=new ScmPair(BEGIN,ScmList.toList(parser.getRemainingDatums())); 44 | }catch(FileNotFoundException|UnsupportedEncodingException ex){ 45 | throw new RuntimeException(); 46 | } 47 | return new Evaluator(env).eval(content); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmListBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | 19 | /** 20 | * A helper that may construct list by reverse order in the structure 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class ScmListBuilder{ 24 | private ScmObject start=ScmNil.NIL; 25 | private ScmPair end=null; 26 | /** 27 | * Prepare for a list 28 | */ 29 | public ScmListBuilder(){ 30 | 31 | } 32 | /** 33 | * Provides a item to be added 34 | * @param item 35 | */ 36 | public void add(ScmObject item){ 37 | ScmPair fresh=new ScmPair(item,ScmNil.NIL); 38 | if(end==null){ 39 | start=end=fresh; 40 | }else{ 41 | end.setCdr(fresh); 42 | end=fresh; 43 | } 44 | } 45 | /** 46 | * Provides some items to be added 47 | * @param list 48 | */ 49 | public void addAll(ScmPairOrNil list){ 50 | ScmList.forEach(list,(item)->add(item)); 51 | } 52 | /** 53 | * Provides some items to be added 54 | * @param buf 55 | */ 56 | public void addAll(ScmListBuilder buf){ 57 | if(end==null){ 58 | start=buf.start; 59 | end=buf.end; 60 | }else if(buf.end!=null){ 61 | end.setCdr(buf.start); 62 | end=buf.end; 63 | } 64 | } 65 | /** 66 | * Set the last item in a partial list 67 | * @param obj 68 | */ 69 | public void setLast(ScmObject obj){ 70 | if(end==null) 71 | start=obj; 72 | else 73 | end.setCdr(obj); 74 | } 75 | /** 76 | * Build the list 77 | * @return the list 78 | */ 79 | public ScmObject toList(){ 80 | return start; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Include.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | import java.io.*; 21 | /** 22 | * Correspoding to the primitive include in Scheme 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class Include extends BasicConstruct implements Primitive{ 26 | public static final Include INSTANCE=new Include("include",false); 27 | public static final Include INSTANCE_CI=new Include("include-ci",true); 28 | private final boolean foldingCase; 29 | private Include(String name,boolean foldingCase){ 30 | super(new ScmSymbol(name)); 31 | this.foldingCase=foldingCase; 32 | } 33 | @Override 34 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil expr){ 35 | cont.callTail(ExpressionEvaluator.INSTANCE,getFileContent((ScmPair)expr),env); 36 | } 37 | ScmObject getFileContent(ScmPair files){ 38 | ScmListBuilder buf=new ScmListBuilder(); 39 | buf.add(new ScmSymbol("begin")); 40 | ScmList.forEach(files,(file)->appendContent(((ScmString)file).getValue(),buf)); 41 | return buf.toList(); 42 | } 43 | private void appendContent(String file,ScmListBuilder buf){ 44 | try{ 45 | Parser parser=new Parser(new Lex(new InputStreamReader(new FileInputStream(Main.resolveFile(file)),"UTF-8"),foldingCase)); 46 | ScmObject datum; 47 | while((datum=parser.nextDatum())!=null) 48 | buf.add(datum); 49 | }catch(FileNotFoundException|UnsupportedEncodingException ex){ 50 | throw new RuntimeException(); 51 | } 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/JavaEnvironment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.util.*; 20 | import javax.script.*; 21 | /** 22 | * Environment backed by ScriptContext 23 | * 24 | * @author Chan Chung Kwong <1m02math@126.com> 25 | */ 26 | public class JavaEnvironment extends Environment{ 27 | private final ScriptContext parent; 28 | /** 29 | * Create a new environment 30 | * 31 | * @param parent the backed ScriptContext 32 | * @param repl REPL mode or not 33 | */ 34 | public JavaEnvironment(ScriptContext parent,boolean repl){ 35 | super(repl); 36 | this.parent=parent; 37 | } 38 | @Override 39 | public Optional getOptional(ScmSymbol id){ 40 | return Optional.ofNullable(getSelfOptional(id)); 41 | } 42 | @Override 43 | public ScmObject getSelfOptional(ScmSymbol id){ 44 | return ScmJavaObject.toScmObject(parent.getAttribute(id.getValue())); 45 | } 46 | @Override 47 | public void set(ScmSymbol id,ScmObject obj){ 48 | int scope=parent.getAttributesScope(id.getValue()); 49 | if(scope!=-1){ 50 | parent.setAttribute(id.getValue(),ScmJavaObject.toJavaObject(obj),scope); 51 | } 52 | if(isREPL()){ 53 | add(id,obj); 54 | } 55 | } 56 | @Override 57 | public void add(ScmSymbol id,ScmObject obj){ 58 | parent.setAttribute(id.getValue(),ScmJavaObject.toJavaObject(obj),parent.getScopes().get(0)); 59 | } 60 | @Override 61 | public void remove(ScmSymbol id){ 62 | int scope=parent.getAttributesScope(id.getValue()); 63 | if(scope!=-1){ 64 | parent.removeAttribute(id.getValue(),scope); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Define.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | import java.util.*; 21 | /** 22 | * Correspoding to the primitive define in Scheme 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class Define extends BasicConstruct implements Primitive{ 26 | public static final Define INSTANCE=new Define(); 27 | private Define(){ 28 | super(new ScmSymbol("define")); 29 | } 30 | @Override 31 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil expr){ 32 | if(pointer==null){ 33 | ScmPair remain=(ScmPair)expr; 34 | if(remain.getCar() instanceof ScmSymbol){ 35 | Optional old=env.getOptional((ScmSymbol)remain.getCar()); 36 | if(!old.isPresent()||isSyntax(old.get())) 37 | env.add((ScmSymbol)remain.getCar(),ScmNil.NIL); 38 | cont.replaceCurrent(this); 39 | cont.call(ExpressionEvaluator.INSTANCE,(ScmSymbol)remain.getCar(),((ScmPair)remain.getCdr()).getCar(),env); 40 | }else if(remain.getCar() instanceof ScmPair){ 41 | ScmSymbol name=(ScmSymbol)((ScmPair)remain.getCar()).getCar(); 42 | ScmProcedure proc=new ScmProcedure(((ScmPair)remain.getCar()).getCdr(),(ScmPair)remain.getCdr(),env); 43 | env.add(name,proc); 44 | cont.ret(proc); 45 | }else 46 | throw new SyntaxException(); 47 | }else{ 48 | env.add((ScmSymbol)pointer,ScmList.first(expr)); 49 | cont.ret(expr); 50 | } 51 | } 52 | private static boolean isSyntax(ScmObject obj){ 53 | return obj instanceof ScmSyntaxRules||obj instanceof Primitive; 54 | } 55 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/DefineRecordType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive define-record-type in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class DefineRecordType extends BasicConstruct implements Primitive{ 25 | public static final DefineRecordType INSTANCE=new DefineRecordType(); 26 | private DefineRecordType(){ 27 | super(new ScmSymbol("define-record-type")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | ScmSymbol name=(ScmSymbol)ScmList.first(param); 32 | param=(ScmPairOrNil)((ScmPair)param).getCdr(); 33 | ScmPair constructor=(ScmPair)ScmList.first(param); 34 | ScmRecordType type=new ScmRecordType(name,constructor.getCdr()); 35 | env.add((ScmSymbol)constructor.getCar(),type.getConstractor()); 36 | param=(ScmPairOrNil)((ScmPair)param).getCdr(); 37 | env.add((ScmSymbol)ScmList.first(param),type.getPredicate()); 38 | param=(ScmPairOrNil)((ScmPair)param).getCdr(); 39 | while(param instanceof ScmPair){ 40 | ScmPair field=(ScmPair)ScmList.first(param); 41 | ScmSymbol fieldname=(ScmSymbol)field.getCar(); 42 | field=(ScmPair)field.getCdr(); 43 | env.add((ScmSymbol)field.getCar(),type.getAccessor(fieldname)); 44 | if(field.getCdr() instanceof ScmPair){ 45 | env.add((ScmSymbol)((ScmPair)field.getCdr()).getCar(),type.getModifier(fieldname)); 46 | } 47 | param=(ScmPairOrNil)((ScmPair)param).getCdr(); 48 | } 49 | cont.ret(type); 50 | } 51 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmComplexPolar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin.type; 16 | /** 17 | * Represents some complex number in Scheme 18 | * @author Chan Chung Kwong <1m02math@126.com> 19 | */ 20 | public class ScmComplexPolar extends ScmComplex{ 21 | private static final ScmFloatingPointNumber TWOPI=ScmFloatingPointNumber.PI.multiply(ScmInteger.TWO.toInExact()); 22 | private static final ScmInteger THREE=new ScmInteger(3); 23 | private final ScmReal abs,radius; 24 | /** 25 | * Construct a complex number 26 | * @param abs 27 | * @param radius 28 | */ 29 | public ScmComplexPolar(ScmReal abs,ScmReal radius){ 30 | this.abs=abs; 31 | if(abs.isZero()){ 32 | this.radius=ScmInteger.ZERO; 33 | }else if(radius instanceof ScmSpecialReal||ScmReal.lessEquals(radius.getMagnitude(),THREE)){ 34 | this.radius=radius; 35 | }else{ 36 | this.radius=radius.subtract(((ScmFloatingPointNumber)radius.divide(TWOPI)).round().multiply(TWOPI)); 37 | } 38 | } 39 | @Override 40 | public ScmReal getAngle(){ 41 | return radius; 42 | } 43 | @Override 44 | public ScmReal getMagnitude(){ 45 | return abs; 46 | } 47 | @Override 48 | public ScmReal getImag(){ 49 | return radius.equals(ScmInteger.ZERO)?ScmInteger.ZERO:abs.multiply(radius.sin()); 50 | } 51 | @Override 52 | public ScmReal getReal(){ 53 | return radius.equals(ScmInteger.ZERO)?abs:abs.multiply(radius.cos()); 54 | } 55 | @Override 56 | public String toExternalRepresentation(int radix){ 57 | return abs.toExternalRepresentation(radix)+"@"+radius.toExternalRepresentation(radix); 58 | } 59 | @Override 60 | public boolean isZero(){ 61 | return abs.isZero(); 62 | } 63 | @Override 64 | public boolean isFinite(){ 65 | return abs.isFinite(); 66 | } 67 | @Override 68 | public boolean isInfinite(){ 69 | return abs.isInfinite(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/File.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.car; 20 | import com.github.chungkwong.jschememin.type.*; 21 | /** 22 | * Correspoding to the library (scheme file) in Scheme 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class File extends NativeLibrary{ 26 | public static final File INSTANCE=new File(); 27 | private File(){ 28 | super("scheme","file"); 29 | } 30 | @Override 31 | protected void init(Library lib){ 32 | addNativeProcedure("file-exists?",(o)->ScmBoolean.valueOf(Main.resolveFile(((ScmString)car(o)).getValue()).exists())); 33 | addNativeProcedure("file-delete",(o)->{ 34 | java.io.File file=Main.resolveFile(((ScmString)car(o)).getValue()); 35 | if(file.exists()&&file.delete()) 36 | return ScmBoolean.TRUE; 37 | else 38 | throw ScmError.toException(new ScmError(new ScmString("Failed to delete file"),ScmList.toList(car(o)),ScmError.ErrorType.FILE)); 39 | }); 40 | addNativeProcedure("open-input-file",(o)->new ScmTextualInputPort(((ScmString)car(o)).getValue())); 41 | addNativeProcedure("open-binary-input-file",(o)->new ScmBinaryInputPort(((ScmString)car(o)).getValue())); 42 | addNativeProcedure("open-output-file",(o)->new ScmTextualOutputPort(((ScmString)car(o)).getValue())); 43 | addNativeProcedure("open-binary-output-file",(o)->new ScmBinaryOutputPort(((ScmString)car(o)).getValue())); 44 | addDeriveFile("/com/github/chungkwong/jschememin/lib/file_derive.scm","call-with-input-file", 45 | "call-with-output-file","with-input-from-file","with-output-to-file"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmComplexRectangular.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or (at 7 | * your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | */ 15 | package com.github.chungkwong.jschememin.type; 16 | /** 17 | * Represents some complex number in Scheme 18 | * @author Chan Chung Kwong <1m02math@126.com> 19 | */ 20 | public class ScmComplexRectangular extends ScmComplex{ 21 | public static final ScmComplexRectangular I=new ScmComplexRectangular(ScmInteger.ZERO,ScmInteger.ONE); 22 | private final ScmReal real,imag; 23 | /** 24 | * Construct a complex number 25 | * @param real 26 | * @param imag 27 | */ 28 | public ScmComplexRectangular(ScmReal real,ScmReal imag){ 29 | this.real=real; 30 | this.imag=imag; 31 | } 32 | @Override 33 | public ScmReal getReal(){ 34 | return real; 35 | } 36 | @Override 37 | public ScmReal getImag(){ 38 | return imag; 39 | } 40 | @Override 41 | public ScmReal getMagnitude(){ 42 | return real.multiply(real).add(imag.multiply(imag)).sqrt().toScmReal(); 43 | } 44 | @Override 45 | public ScmReal getAngle(){ 46 | if(real.isPositive()&&imag.isZero()) 47 | return ScmInteger.ZERO; 48 | else 49 | return ScmFloatingPointNumber.valueOf(Math.atan2(ScmFloatingPointNumber.toDouble(imag) 50 | ,ScmFloatingPointNumber.toDouble(real))); 51 | } 52 | @Override 53 | public boolean isZero(){ 54 | return real.isZero()&&imag.isZero(); 55 | } 56 | @Override 57 | public boolean isFinite(){ 58 | return real.isFinite()&&imag.isFinite(); 59 | } 60 | @Override 61 | public boolean isInfinite(){ 62 | return real.isInfinite()||imag.isInfinite(); 63 | } 64 | @Override 65 | public String toExternalRepresentation(int radix){ 66 | StringBuilder buf=new StringBuilder(); 67 | buf.append(real.toExternalRepresentation(radix)); 68 | if(imag.needPlusSign()) 69 | buf.append('+'); 70 | buf.append(imag.toExternalRepresentation(radix)); 71 | buf.append("i"); 72 | return buf.toString(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmRecord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | import java.util.*; 19 | /** 20 | * Represents records in Scheme 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class ScmRecord extends ScmObject{ 24 | private final ScmRecordType type; 25 | private final ScmObject[] fields; 26 | /** 27 | * Create a record 28 | * @param type the type of the record 29 | * @param fields the fields that the record have 30 | */ 31 | public ScmRecord(ScmRecordType type,ScmObject[] fields){ 32 | this.type=type; 33 | this.fields=fields; 34 | } 35 | ScmObject get(int i){ 36 | return fields[i]; 37 | } 38 | void set(int i,ScmObject obj){ 39 | fields[i]=obj; 40 | } 41 | /** 42 | * Get the type of the record 43 | * @return the type 44 | */ 45 | public ScmRecordType getType(){ 46 | return type; 47 | } 48 | @Override 49 | public String toExternalRepresentation(){ 50 | ScmListBuilder buf=new ScmListBuilder(); 51 | buf.add(type.getName()); 52 | type.indices.forEach((key,value)->buf.add(new ScmPair(key,fields[value]))); 53 | return buf.toList().toString(); 54 | } 55 | @Override 56 | public boolean isSelfevaluating(){ 57 | return false; 58 | } 59 | @Override 60 | public boolean equals(Object obj){ 61 | return obj instanceof ScmRecord&&((ScmRecord)obj).type.equals(type) 62 | &&Arrays.equals(((ScmRecord)obj).fields,fields); 63 | } 64 | @Override 65 | public boolean equalsValue(ScmObject obj){ 66 | return this==obj; 67 | } 68 | @Override 69 | public int hashCode(){ 70 | int hash=5; 71 | hash=83*hash+Objects.hashCode(this.type); 72 | hash=83*hash+Arrays.deepHashCode(this.fields); 73 | return hash; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ObjectPair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | import java.util.*; 19 | /** 20 | * 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | class ObjectPair{ 24 | private final Object car,cdr; 25 | private ObjectPair(Object car,Object cdr){ 26 | this.car=car; 27 | this.cdr=cdr; 28 | } 29 | @Override 30 | public boolean equals(Object obj){ 31 | return obj instanceof ObjectPair&&((ObjectPair)obj).car==car&&((ObjectPair)obj).cdr==cdr; 32 | } 33 | @Override 34 | public int hashCode(){ 35 | int hash=7; 36 | hash=23*hash+System.identityHashCode(car); 37 | hash=23*hash+System.identityHashCode(cdr); 38 | return hash; 39 | } 40 | static boolean equals(Object a,Object b,HashSet found){ 41 | if(a instanceof ScmPair&&b instanceof ScmPair){ 42 | ScmPair c=(ScmPair)a,d=(ScmPair)b; 43 | ObjectPair pair=new ObjectPair(a,b); 44 | if(found.contains(pair)) 45 | return true; 46 | else{ 47 | found.add(pair); 48 | return equals(c.getCar(),d.getCar(),found)&&equals(c.getCdr(),d.getCdr(),found); 49 | } 50 | }else if(a instanceof ScmVector&& b instanceof ScmVector){ 51 | ScmVector c=(ScmVector)a,d=(ScmVector)b; 52 | ObjectPair pair=new ObjectPair(a,b); 53 | if(found.contains(pair)) 54 | return true; 55 | else{ 56 | found.add(pair); 57 | if(c.getLength()==d.getLength()) 58 | for(int i=0;i 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.cadr; 20 | import static com.github.chungkwong.jschememin.lib.Utility.car; 21 | import static com.github.chungkwong.jschememin.lib.Utility.cdr; 22 | import com.github.chungkwong.jschememin.type.*; 23 | /** 24 | * Correspoding to the library (scheme inexact) in Scheme 25 | * @author Chan Chung Kwong <1m02math@126.com> 26 | */ 27 | public class Inexact extends NativeLibrary{ 28 | public static final Inexact INSTANCE=new Inexact(); 29 | private Inexact(){ 30 | super("scheme","inexact"); 31 | } 32 | @Override 33 | protected void init(Library lib){ 34 | addNativeProcedure("finite?",(o)->ScmBoolean.valueOf(((ScmComplex)car(o)).isFinite())); 35 | addNativeProcedure("infinite?",(o)->ScmBoolean.valueOf(((ScmComplex)car(o)).isInfinite())); 36 | addNativeProcedure("nan?",(o)->ScmBoolean.valueOf(((ScmComplex)car(o)).isNaN())); 37 | addNativeProcedure("log",(o)->cdr(o)instanceof ScmNil?((ScmComplex)car(o)).log():((ScmComplex)car(o)).log((ScmComplex)cadr(o))); 38 | addNativeProcedure("exp",(o)->((ScmComplex)car(o)).exp()); 39 | addNativeProcedure("sin",(o)->((ScmComplex)car(o)).sin()); 40 | addNativeProcedure("cos",(o)->((ScmComplex)car(o)).cos()); 41 | addNativeProcedure("tan",(o)->((ScmComplex)car(o)).tan()); 42 | addNativeProcedure("asin",(o)->((ScmComplex)car(o)).arcsin()); 43 | addNativeProcedure("acos",(o)->((ScmComplex)car(o)).arccos()); 44 | addNativeProcedure("atan",new NativeProcedureDefault( 45 | (o)->new ScmComplexRectangular(((ScmComplex)cadr(o)).toScmReal(),((ScmComplex)car(o)).toScmReal()).getAngle(), 46 | (o)->car(o),(o)->ScmInteger.ONE)); 47 | addNativeProcedure("sqrt",(o)->((ScmComplex)car(o)).sqrt()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/DynamicWind.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | /** 21 | * Correspoding to the primitive dynamic-wind in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class DynamicWind extends BasicConstruct{ 25 | public static final DynamicWind INSTANCE=new DynamicWind(); 26 | private DynamicWind(){ 27 | super(new ScmSymbol("dynamic-wind")); 28 | } 29 | @Override 30 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil param){ 31 | if(pointer==null){ 32 | Backtrack track=new Backtrack((Evaluable)ScmList.first(param), 33 | (Evaluable)ScmList.second(param),(Evaluable)ScmList.third(param),false); 34 | cont.call(track.getBefore(),track,ScmNil.NIL,env); 35 | }else if(pointer instanceof Backtrack){ 36 | Backtrack old=(Backtrack)pointer; 37 | if(old.isStarted()) 38 | cont.call(((Backtrack)pointer).getAfter(),param,ScmNil.NIL,env); 39 | else 40 | cont.call(((Backtrack)pointer).getThunk(),new Backtrack(old.getBefore(),old.getThunk(),old.getAfter(),true),ScmNil.NIL,env); 41 | }else{ 42 | cont.ret((ScmPairOrNil)pointer); 43 | } 44 | } 45 | public static class Backtrack{ 46 | private final Evaluable before; 47 | private final Evaluable thunk; 48 | private final Evaluable after; 49 | private final boolean started; 50 | public Backtrack(Evaluable before,Evaluable thunk,Evaluable after,boolean started){ 51 | this.before=before; 52 | this.thunk=thunk; 53 | this.after=after; 54 | this.started=started; 55 | } 56 | public Evaluable getBefore(){ 57 | return before; 58 | } 59 | public Evaluable getThunk(){ 60 | return thunk; 61 | } 62 | public Evaluable getAfter(){ 63 | return after; 64 | } 65 | public boolean isStarted(){ 66 | return started; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Evaluator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.io.*; 20 | import javax.script.*; 21 | /** 22 | * Evaluator for Scheme 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class Evaluator extends AbstractScriptEngine{ 26 | private final SchemeEnvironment env; 27 | /** 28 | * Create a evaluator 29 | * @param repl REPL mode or not 30 | */ 31 | public Evaluator(boolean repl){ 32 | this(new SchemeEnvironment(repl)); 33 | } 34 | /** 35 | * Create a evaluator 36 | * @param env top-level environemnt 37 | */ 38 | public Evaluator(SchemeEnvironment env){ 39 | this.env=env; 40 | } 41 | /** 42 | * Evaluate a expression 43 | * @param expr the expression 44 | * @return the value 45 | */ 46 | public ScmObject eval(ScmObject expr){ 47 | Continuation cont=new Continuation(); 48 | cont.callInit(ExpressionEvaluator.INSTANCE,expr,env); 49 | while(cont.hasNext()) 50 | cont.evalNext(); 51 | return cont.getCurrentValue(); 52 | } 53 | /** 54 | * Get the top level environment 55 | * @return 56 | */ 57 | public SchemeEnvironment getEnvironment(){ 58 | return env; 59 | } 60 | @Override 61 | public Object eval(String script,ScriptContext context) throws ScriptException{ 62 | return eval(new StringReader(script),context); 63 | } 64 | @Override 65 | public Object eval(Reader reader,ScriptContext context) throws ScriptException{ 66 | Parser parser=new Parser(new Lex(reader)); 67 | env.setParent(new JavaEnvironment(context,env.isREPL())); 68 | ScmObject datum,ret=null; 69 | while((datum=parser.nextDatum())!=null){ 70 | ret=eval(datum); 71 | } 72 | return ret; 73 | } 74 | @Override 75 | public Bindings createBindings(){ 76 | Bindings bindings=new SimpleBindings(); 77 | return bindings; 78 | } 79 | @Override 80 | public ScriptEngineFactory getFactory(){ 81 | return EvaluatorFactory.INSTANCE; 82 | } 83 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/r5rs.scm: -------------------------------------------------------------------------------- 1 | (define-library (scheme r5rs) 2 | (import (scheme base) (scheme char) (scheme complex) (scheme cxr) (scheme eval) (scheme file) (scheme inexact) (scheme load)) 3 | (export * + - / < <= = > >= abs acos and angle append apply asin assoc assq assv atan 4 | begin boolean? caaaar caaadr caaar caadar caaddr caadr caar cadaar cadadr cadar caddar cadddr caddr cadr 5 | call-with-current-continuation call-with-input-file call-with-output-file call-with-values 6 | car case cdaaar cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar cdddar cddddr cdddr cddr cdr 7 | ceiling char->integer char-alphabetic? char-ci<=? char-ci=? char-ci>? 8 | char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? 9 | char<=? char=? char>? char? close-input-port close-output-port complex? cond cons cos 10 | current-input-port current-output-port define define-syntax delay denominator display do dynamic-wind 11 | eof-object? eq? equal? eqv? eval even? (rename inexact exact->inexact) exact? exp expt floor for-each force 12 | gcd if imag-part (rename exact inexact->exact) inexact? input-port? integer->char integer? 13 | interaction-environment lambda lcm length let let* let-syntax letrec letrec-syntax list list->string 14 | list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector 15 | map max member memq memv min modulo negative? newline not null? number->string number? numerator 16 | odd? open-input-file open-output-file or output-port? pair? peek-char positive? procedure? 17 | quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round 18 | set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append 19 | string-ci<=? string-ci=? string-ci>? string-copy string-fill! string-length 20 | string-ref string-set! string<=? string=? string>? string? substring 21 | symbol->string symbol? tan truncate values vector vector->list vector-fill! vector-length vector-ref 22 | vector-set! vector? with-input-from-file with-output-to-file write write-char zero? 23 | null-environment scheme-report-environment) 24 | (begin 25 | (define (null-environment version) (case version 26 | ((5) (environment '(scheme null))) 27 | (else (raise 'not5)))) 28 | (define (scheme-report-environment version) (case version ((5) (environment '(scheme r5rs))) (else (raise 'not5)))))) -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Library.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.util.*; 20 | /** 21 | * Library in scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class Library extends ScmObject{ 25 | private final ScmPair name; 26 | private final HashMap export; 27 | private final SchemeEnvironment internal; 28 | /** 29 | * Create a library 30 | * @param name the name 31 | * @param export the export name mapping 32 | * @param internal internal environment 33 | */ 34 | public Library(ScmPair name,HashMap export,SchemeEnvironment internal){ 35 | this.name=name; 36 | this.export=export; 37 | this.internal=internal; 38 | LibraryManager.addLibrary(this); 39 | } 40 | /** 41 | * Get the name 42 | * @return 43 | */ 44 | public ScmPair getName(){ 45 | return name; 46 | } 47 | /** 48 | * Get the exported names 49 | * @return 50 | */ 51 | public Set getExportSet(){ 52 | return export.keySet(); 53 | } 54 | /** 55 | * Get the export name mapping 56 | * @return 57 | */ 58 | public HashMap getExportMap(){ 59 | return export; 60 | } 61 | /** 62 | * Export the library to a environment 63 | * @param env 64 | */ 65 | public void exportTo(Environment env){ 66 | export.forEach((ex,im)->env.add(ex,internal.get(im))); 67 | } 68 | /** 69 | * Export some names in the library to a environment 70 | * @param env 71 | * @param importset 72 | */ 73 | public void exportTo(Environment env,HashMap importset){ 74 | importset.forEach((ex,im)->env.add(im,internal.get(export.get(ex)))); 75 | } 76 | /** 77 | * Get the internal environment 78 | * @return 79 | */ 80 | public SchemeEnvironment getInternalEnvironment(){ 81 | return internal; 82 | } 83 | @Override 84 | public String toExternalRepresentation(){ 85 | return name.toString(); 86 | } 87 | @Override 88 | public boolean isSelfevaluating(){ 89 | return false; 90 | } 91 | } -------------------------------------------------------------------------------- /test/com/github/chungkwong/jschememin/lib-example.scm: -------------------------------------------------------------------------------- 1 | (define-library (example grid) 2 | (export make rows cols ref each 3 | (rename put! set!)) 4 | (import (scheme base)) 5 | (begin 6 | ;; Create an NxM grid. 7 | (define (make n m) 8 | (let ((grid (make-vector n))) 9 | (do ((i 0 (+ i 1))) 10 | ((= i n) grid) 11 | (let ((v (make-vector m #f))) 12 | (vector-set! grid i v))))) 13 | (define (rows grid) 14 | (vector-length grid)) 15 | (define (cols grid) 16 | (vector-length (vector-ref grid 0))) 17 | ;; Return #f if out of range. 18 | (define (ref grid n m) 19 | (and (< -1 n (rows grid)) 20 | (< -1 m (cols grid)) 21 | (vector-ref (vector-ref grid n) m))) 22 | (define (put! grid n m v) 23 | (vector-set! (vector-ref grid n) m v)) 24 | (define (each grid proc) 25 | (do ((j 0 (+ j 1))) 26 | ((= j (rows grid))) 27 | (do ((k 0 (+ k 1))) 28 | ((= k (cols grid))) 29 | (proc j k (ref grid j k))))))) 30 | 31 | (define-library (example life) 32 | (export life) 33 | (import (except (scheme base) set!) 34 | (scheme write) 35 | (example grid)) 36 | (begin 37 | (define (life-count grid i j) 38 | (define (count i j) 39 | (if (ref grid i j) 1 0)) 40 | (+ (count (- i 1) (- j 1)) 41 | (count (- i 1) j) 42 | (count (- i 1) (+ j 1)) 43 | (count i (- j 1)) 44 | (count i (+ j 1)) 45 | (count (+ i 1) (- j 1)) 46 | (count (+ i 1) j) 47 | (count (+ i 1) (+ j 1)))) 48 | (define (life-alive? grid i j) 49 | (case (life-count grid i j) 50 | ((3) #t) 51 | ((2) (ref grid i j)) 52 | (else #f))) 53 | (define (life-print grid) 54 | (each grid 55 | (lambda (i j v) 56 | (display (if v "*" " ")) 57 | (when (= j (- (cols grid) 1)) 58 | (newline))))) 59 | (define (life grid iterations) 60 | (do ((i 0 (+ i 1)) 61 | (grid0 grid grid1) 62 | (grid1 (make (rows grid) (cols grid)) 63 | grid0)) 64 | ((= i iterations)) 65 | (each grid0 66 | (lambda (j k v) 67 | (let ((a (life-alive? grid0 j k))) 68 | (set! grid1 j k a)))) 69 | (life-print grid1))))) 70 | 71 | ;; Main program. 72 | (import (scheme base) 73 | (only (example life) life) 74 | (rename (prefix (example grid) grid-) 75 | (grid-make make-grid))) 76 | 77 | ;; Initialize a grid with a glider. 78 | (define grid (make-grid 5 6)) 79 | (grid-set! grid 1 1 #t) 80 | (grid-set! grid 2 2 #t) 81 | (grid-set! grid 3 0 #t) 82 | (grid-set! grid 3 1 #t) 83 | (grid-set! grid 3 2 #t) 84 | 85 | ;; Run for 80 iterations. 86 | (life grid 3) 87 | (flush-output-port) -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmNormalReal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | 19 | /** 20 | * Represents most reals in Scheme 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public abstract class ScmNormalReal extends ScmReal implements Comparable{ 24 | @Override 25 | public abstract ScmNormalReal negate(); 26 | @Override 27 | public abstract ScmNormalReal floor(); 28 | @Override 29 | public abstract ScmNormalReal ceiling(); 30 | @Override 31 | public abstract ScmNormalReal truncate(); 32 | @Override 33 | public abstract ScmNormalReal round(); 34 | public abstract int signum(); 35 | @Override 36 | public abstract ScmFloatingPointNumber toInExact(); 37 | @Override 38 | public boolean isZero(){ 39 | return signum()==0; 40 | } 41 | @Override 42 | public boolean isPositive(){ 43 | return signum()>0; 44 | } 45 | @Override 46 | public boolean isNegative(){ 47 | return signum()<0; 48 | } 49 | @Override 50 | public ScmComplex log(){ 51 | return toInExact().log(); 52 | } 53 | @Override 54 | public ScmComplex sqrt(){ 55 | return toInExact().sqrt(); 56 | } 57 | @Override 58 | public ScmReal exp(){ 59 | return toInExact().exp(); 60 | } 61 | @Override 62 | public ScmReal sin(){ 63 | return toInExact().sin(); 64 | } 65 | @Override 66 | public ScmReal cos(){ 67 | return toInExact().cos(); 68 | } 69 | @Override 70 | public ScmReal getAngle(){ 71 | int sign=signum(); 72 | if(sign>0) 73 | return ScmInteger.ZERO; 74 | else if(sign<0) 75 | return ScmFloatingPointNumber.PI; 76 | else 77 | return ScmSpecialReal.POSITIVE_NAN; 78 | } 79 | @Override 80 | public boolean isFinite(){ 81 | return true; 82 | } 83 | @Override 84 | public boolean isInfinite(){ 85 | return false; 86 | } 87 | @Override 88 | public boolean isRational(){ 89 | return true; 90 | } 91 | @Override 92 | public boolean isInteger(){ 93 | return equals(truncate()); 94 | } 95 | @Override 96 | public double toDouble(){ 97 | return toInExact().getValue().doubleValue(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/SchemeEnvironment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.lib.*; 19 | import com.github.chungkwong.jschememin.primitive.*; 20 | import com.github.chungkwong.jschememin.type.*; 21 | import java.util.*; 22 | /** 23 | * Standard environment 24 | * @author Chan Chung Kwong <1m02math@126.com> 25 | */ 26 | public class SchemeEnvironment extends Environment{ 27 | private Environment parent; 28 | private final HashMap bindings=new HashMap<>(); 29 | /** 30 | * Create a top-level environment 31 | * @param repl REPL mode or not 32 | */ 33 | public SchemeEnvironment(boolean repl){ 34 | super(repl); 35 | this.parent=null; 36 | bindings.put(DefineLibrary.INSTANCE.getKeyword(),DefineLibrary.INSTANCE); 37 | bindings.put(Import.INSTANCE.getKeyword(),Import.INSTANCE); 38 | if(repl) 39 | Base.INSTANCE.getLibrary().exportTo(this); 40 | } 41 | void setParent(Environment parent){ 42 | this.parent=parent; 43 | } 44 | /** 45 | * Create a envionment 46 | * @param parent parent environment 47 | */ 48 | public SchemeEnvironment(Environment parent){ 49 | super(parent.isREPL()); 50 | this.parent=parent; 51 | } 52 | @Override 53 | public Optional getOptional(ScmSymbol id){ 54 | Environment env=getFirstEnvironmentContains(this,id); 55 | return env!=null?Optional.ofNullable(env.getSelfOptional(id)):Optional.empty(); 56 | } 57 | @Override 58 | public ScmObject getSelfOptional(ScmSymbol id){ 59 | return bindings.get(id); 60 | } 61 | @Override 62 | public void set(ScmSymbol id,ScmObject obj){ 63 | Environment env=getFirstEnvironmentContains(this,id); 64 | if(env!=null){ 65 | env.add(id,obj); 66 | }else if(isREPL()) 67 | add(id,obj); 68 | } 69 | private static Environment getFirstEnvironmentContains(Environment env,ScmSymbol id){ 70 | while(env instanceof SchemeEnvironment){ 71 | if(((SchemeEnvironment)env).bindings.containsKey(id)) 72 | break; 73 | env=((SchemeEnvironment)env).parent; 74 | } 75 | return env; 76 | } 77 | @Override 78 | public void add(ScmSymbol id,ScmObject obj){ 79 | bindings.put(id,obj); 80 | } 81 | @Override 82 | public void remove(ScmSymbol id){ 83 | bindings.remove(id); 84 | } 85 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/EvaluatorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.util.*; 20 | import java.util.stream.*; 21 | import javax.script.*; 22 | /** 23 | * An implementation of ScriptEngineFactory 24 | * @author Chan Chung Kwong <1m02math@126.com> 25 | */ 26 | public class EvaluatorFactory implements ScriptEngineFactory{ 27 | /** 28 | * The factory for jSchemeMin 29 | */ 30 | public static final EvaluatorFactory INSTANCE=new EvaluatorFactory(); 31 | private static final HashMap PARAMETERS=new HashMap<>(); 32 | static{ 33 | PARAMETERS.put("ScriptEngine.ENGINE","JSchemeMin"); 34 | PARAMETERS.put("ScriptEngine.ENGINE_VERSION","0.0.1"); 35 | PARAMETERS.put("ScriptEngine.NAME","JSchemeMin"); 36 | PARAMETERS.put("ScriptEngine.LANGUAGE","scheme"); 37 | PARAMETERS.put("ScriptEngine.LANGUAGE_VERSION","7"); 38 | } 39 | private EvaluatorFactory(){ 40 | 41 | } 42 | @Override 43 | public String getEngineName(){ 44 | return PARAMETERS.get("ScriptEngine.ENGINE"); 45 | } 46 | @Override 47 | public String getEngineVersion(){ 48 | return PARAMETERS.get("ScriptEngine.ENGINE_VERSION"); 49 | } 50 | @Override 51 | public List getExtensions(){ 52 | return Arrays.asList("scm"); 53 | } 54 | @Override 55 | public List getMimeTypes(){ 56 | return Arrays.asList("text/x-scheme"); 57 | } 58 | @Override 59 | public List getNames(){ 60 | return Arrays.asList(PARAMETERS.get("ScriptEngine.NAME")); 61 | } 62 | @Override 63 | public String getLanguageName(){ 64 | return PARAMETERS.get("ScriptEngine.LANGUAGE_NAME"); 65 | } 66 | @Override 67 | public String getLanguageVersion(){ 68 | return PARAMETERS.get("ScriptEngine.LANGUAGE_VERSION"); 69 | } 70 | @Override 71 | public Object getParameter(String key){ 72 | return PARAMETERS.get(key); 73 | } 74 | @Override 75 | public String getMethodCallSyntax(String obj,String m,String... args){ 76 | return Arrays.stream(args).collect(Collectors.joining(" ","("+m,")")); 77 | } 78 | @Override 79 | public String getOutputStatement(String toDisplay){ 80 | return "(write-string "+new ScmString(toDisplay).toExternalRepresentation()+")"; 81 | } 82 | @Override 83 | public String getProgram(String... statements){ 84 | return Arrays.stream(statements).collect(Collectors.joining(" ","(begin ",")")); 85 | } 86 | @Override 87 | public Evaluator getScriptEngine(){ 88 | return new Evaluator(true); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/Environment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.type.*; 19 | import java.util.*; 20 | /** 21 | * Environment where variable is stored 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public abstract class Environment extends ScmObject{ 25 | /** 26 | * The value of unbound variable if in REPL mode 27 | */ 28 | public static final ScmSymbol UNBOUNDED=new ScmSymbol("unbound"); 29 | private final boolean repl; 30 | /** 31 | * Create a environment 32 | * @param repl REPL mode or not 33 | */ 34 | public Environment(boolean repl){ 35 | this.repl=repl; 36 | } 37 | /** 38 | * Get the value of a variable 39 | * @param id name 40 | * @return value in Optional 41 | */ 42 | public abstract Optional getOptional(ScmSymbol id); 43 | /** 44 | * Set a variable 45 | * @param id name 46 | * @param obj value 47 | */ 48 | public abstract void set(ScmSymbol id,ScmObject obj); 49 | /** 50 | * Add a variable 51 | * @param id name 52 | * @param obj value 53 | */ 54 | public abstract void add(ScmSymbol id,ScmObject obj); 55 | /** 56 | * Get the value of a variable in this environment, not its parent 57 | * @param id 58 | * @return value in Optional 59 | */ 60 | public abstract ScmObject getSelfOptional(ScmSymbol id); 61 | /** 62 | * Delete a variable 63 | * @param id name 64 | */ 65 | public abstract void remove(ScmSymbol id); 66 | /** 67 | * Get the value of a variable 68 | * @param id the name of the variable 69 | * @return 70 | */ 71 | public ScmObject get(ScmSymbol id){ 72 | Optional obj=getOptional(id); 73 | if(obj.isPresent()) 74 | return obj.get(); 75 | else 76 | return repl?UNBOUNDED:null; 77 | } 78 | /** 79 | * Check if a variable exists 80 | * @param id the name of the variable 81 | * @return 82 | */ 83 | public boolean containsKey(ScmSymbol id){ 84 | return getOptional(id).isPresent(); 85 | } 86 | /** 87 | * Add a keyword 88 | * @param keyword 89 | */ 90 | public void addPrimitiveType(BasicConstruct keyword){ 91 | add(keyword.getKeyword(),keyword); 92 | } 93 | /** 94 | * Check if in REPL mode 95 | * @return 96 | */ 97 | public boolean isREPL(){ 98 | return repl; 99 | } 100 | @Override 101 | public String toExternalRepresentation(){ 102 | return "'environment"; 103 | //return '\"'+bindings.toString()+'\"'; 104 | } 105 | @Override 106 | public boolean isSelfevaluating(){ 107 | return false; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/LibraryManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin; 18 | import com.github.chungkwong.jschememin.lib.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | import java.util.*; 21 | /** 22 | * 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class LibraryManager{ 26 | private static final HashMap LIBRARIES=new HashMap<>(); 27 | private static final HashMap NATIVE_LIBRARIES=new HashMap<>(); 28 | static{ 29 | addNativeLibrary(Base.INSTANCE); 30 | addNativeLibrary(Char.INSTANCE); 31 | addNativeLibrary(Complex.INSTANCE); 32 | addNativeLibrary(Eval.INSTANCE); 33 | addNativeLibrary(File.INSTANCE); 34 | addNativeLibrary(HashTable.INSTANCE); 35 | addNativeLibrary(Inexact.INSTANCE); 36 | addNativeLibrary(Java.INSTANCE); 37 | addNativeLibrary(JSchemeMin.INSTANCE); 38 | addNativeLibrary(Lazy.INSTANCE); 39 | addNativeLibrary(Load.INSTANCE); 40 | addNativeLibrary(ProcessContext.INSTANCE); 41 | addNativeLibrary(REPL.INSTANCE); 42 | addNativeLibrary(Read.INSTANCE); 43 | addNativeLibrary(Time.INSTANCE); 44 | addNativeLibrary(Write.INSTANCE); 45 | addNativeLibrary(new SimpleLibrary("/com/github/chungkwong/jschememin/lib/case-lambda.scm","scheme","case-lambda")); 46 | addNativeLibrary(new SimpleLibrary("/com/github/chungkwong/jschememin/lib/cxr.scm","scheme","cxr")); 47 | addNativeLibrary(new SimpleLibrary("/com/github/chungkwong/jschememin/lib/lazy.scm","scheme","lazy")); 48 | addNativeLibrary(new SimpleLibrary("/com/github/chungkwong/jschememin/lib/null.scm","scheme","null")); 49 | addNativeLibrary(new SimpleLibrary("/com/github/chungkwong/jschememin/lib/r5rs.scm","scheme","r5rs")); 50 | } 51 | private static void addNativeLibrary(LibraryLoader lib){ 52 | NATIVE_LIBRARIES.put(lib.getName(),lib); 53 | } 54 | /** 55 | * Registry a library 56 | * @param lib 57 | */ 58 | public static void addLibrary(Library lib){ 59 | LIBRARIES.put(lib.getName(),lib); 60 | } 61 | /** 62 | * Check if a library is available 63 | * @param name the name of the library 64 | * @return 65 | */ 66 | public static boolean hasLibrary(ScmPair name){ 67 | return LIBRARIES.containsKey(name)||NATIVE_LIBRARIES.containsKey(name); 68 | } 69 | /** 70 | * Get a library 71 | * @param name the name of the library 72 | * @return 73 | */ 74 | public static Library getLibrary(ScmPair name){ 75 | if(LIBRARIES.containsKey(name)) 76 | return LIBRARIES.get(name); 77 | else if(NATIVE_LIBRARIES.containsKey(name)) 78 | return NATIVE_LIBRARIES.get(name).getLibrary(); 79 | else 80 | throw new RuntimeException("Library not found: "+name); 81 | } 82 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmProcedure.java: -------------------------------------------------------------------------------- 1 | package com.github.chungkwong.jschememin.type; 2 | import com.github.chungkwong.jschememin.*; 3 | /** 4 | * Represents the type procedure in Scheme 5 | * @author kwong 6 | */ 7 | public final class ScmProcedure extends Evaluable{ 8 | private final SchemeEnvironment parent; 9 | private final ScmObject formal; 10 | private final ScmPair body; 11 | /** 12 | * Construct a procedure 13 | * @param formal the formal parameters 14 | * @param body the body 15 | * @param parent the environment where the procedure is defined 16 | */ 17 | public ScmProcedure(ScmObject formal,ScmPair body,SchemeEnvironment parent){ 18 | this.formal=formal; 19 | this.body=body; 20 | this.parent=parent; 21 | } 22 | @Override 23 | public String toExternalRepresentation(){ 24 | StringBuilder buf=new StringBuilder(); 25 | buf.append("(lambda ").append(formal.toExternalRepresentation()).append(' ').append(body.getCar().toExternalRepresentation()); 26 | ScmPair tmp=body; 27 | while(tmp.getCdr() instanceof ScmPair){ 28 | tmp=(ScmPair)tmp.getCdr(); 29 | buf.append(' ').append(tmp.getCar().toExternalRepresentation()); 30 | } 31 | buf.append(')'); 32 | return buf.toString(); 33 | } 34 | @Override 35 | public boolean isSelfevaluating(){ 36 | return false; 37 | } 38 | @Override 39 | public void call(SchemeEnvironment dynamicEnv,Continuation cont,Object pointer,ScmPairOrNil param){ 40 | if(pointer==null){ 41 | call(dynamicEnv,cont,new Backtrack(extendEnvironment((ScmPairOrNil)param),body),null); 42 | }else{ 43 | assert pointer instanceof Backtrack; 44 | Backtrack b=(Backtrack)pointer; 45 | ScmObject next=b.getRemaining().getCdr(); 46 | if(next==ScmNil.NIL){ 47 | cont.callTail(ExpressionEvaluator.INSTANCE,b.getRemaining().getCar(),b.getEnvironment()); 48 | }else if(next instanceof ScmPair){ 49 | cont.call(ExpressionEvaluator.INSTANCE,new Backtrack(b.getEnvironment(),(ScmPair)next),b.getRemaining().getCar(),b.getEnvironment()); 50 | }else 51 | throw new SyntaxException(); 52 | } 53 | } 54 | @Override 55 | public boolean equalsValue(ScmObject obj){ 56 | return this==obj; 57 | } 58 | private SchemeEnvironment extendEnvironment(ScmPairOrNil param){ 59 | SchemeEnvironment env=new SchemeEnvironment(parent); 60 | if(formal instanceof ScmSymbol){ 61 | env.add((ScmSymbol)formal,param); 62 | }else if(formal instanceof ScmPair){ 63 | ScmPair remainingFormal=(ScmPair)formal; 64 | while(true){ 65 | env.add((ScmSymbol)remainingFormal.getCar(),ScmList.first(param)); 66 | param=(ScmPairOrNil)((ScmPair)param).getCdr(); 67 | ScmObject next=remainingFormal.getCdr(); 68 | if(next instanceof ScmPair){ 69 | remainingFormal=(ScmPair)next; 70 | }else if(next instanceof ScmNil){ 71 | break; 72 | }else if(next instanceof ScmSymbol){ 73 | env.add((ScmSymbol)next,param); 74 | break; 75 | }else 76 | throw new SyntaxException(); 77 | } 78 | }else if(formal instanceof ScmNil){ 79 | 80 | }else 81 | throw new SyntaxException(); 82 | return env; 83 | } 84 | static class Backtrack{ 85 | private final SchemeEnvironment env; 86 | private final ScmPair remaining; 87 | public Backtrack(SchemeEnvironment env,ScmPair remaining){ 88 | this.env=env; 89 | this.remaining=remaining; 90 | } 91 | public SchemeEnvironment getEnvironment(){ 92 | return env; 93 | } 94 | public ScmPair getRemaining(){ 95 | return remaining; 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmBinaryOutputPort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | import com.github.chungkwong.jschememin.*; 19 | import java.io.*; 20 | /** 21 | * Represents the type binary output port in Scheme 22 | * @author Chan Chung Kwong <1m02math@126.com> 23 | */ 24 | public class ScmBinaryOutputPort extends ScmPort{ 25 | private final OutputStream out; 26 | /** 27 | * Wrap a OutputStream 28 | * @param out 29 | */ 30 | public ScmBinaryOutputPort(OutputStream out){ 31 | this.out=out; 32 | } 33 | /** 34 | * Construct a port to write to a file 35 | * @param file the file name 36 | */ 37 | public ScmBinaryOutputPort(String file){ 38 | try{ 39 | this.out=new FileOutputStream(Main.resolveFile(file)); 40 | }catch(FileNotFoundException ex){ 41 | throw ScmError.toException(new ScmError(new ScmString(ex.getLocalizedMessage()),ScmNil.NIL,ScmError.ErrorType.FILE)); 42 | } 43 | } 44 | /** 45 | * Corresponding to the procedure write-u8 in Scheme 46 | * @param obj 47 | * @return 48 | * @throws IOException 49 | */ 50 | public ScmBinaryOutputPort writeByte(ScmInteger obj) throws IOException{ 51 | int b=obj.getValue().intValueExact(); 52 | if(b>=0&&b<256) 53 | out.write(b); 54 | else 55 | throw new RuntimeException("A byte is expected"); 56 | return this; 57 | } 58 | /** 59 | * Corresponding to the procedure write-bytevector in Scheme 60 | * @param obj 61 | * @param start 62 | * @param end 63 | * @return 64 | * @throws IOException 65 | */ 66 | public ScmBinaryOutputPort writeByteVector(ScmByteVector obj,int start,int end) throws IOException{ 67 | out.write(obj.getByteArray(),start,end-start); 68 | return this; 69 | } 70 | /** 71 | * Corresponding to the procedure get-output-bytevector in Scheme 72 | * @return 73 | */ 74 | public byte[] getByteArray(){ 75 | if(out instanceof ByteArrayOutputStream) 76 | return ((ByteArrayOutputStream)out).toByteArray(); 77 | else 78 | throw new RuntimeException(); 79 | } 80 | /** 81 | * Corresponding to the procedure flush-output-port in Scheme 82 | * @return 83 | * @throws IOException 84 | */ 85 | public ScmBinaryOutputPort flush()throws IOException{ 86 | out.flush(); 87 | return this; 88 | } 89 | /** 90 | * Corresponding to the procedure close-output-port in Scheme 91 | * @return 92 | * @throws IOException 93 | */ 94 | @Override 95 | public ScmBinaryOutputPort close()throws IOException{ 96 | super.close(); 97 | out.close(); 98 | return this; 99 | } 100 | @Override 101 | public String toExternalRepresentation(){ 102 | return out.toString(); 103 | } 104 | } -------------------------------------------------------------------------------- /doc/overview.tex: -------------------------------------------------------------------------------- 1 | \documentclass[twoside,twocolumn]{algol60} 2 | 3 | \usepackage[slantfont,boldfont]{xeCJK} 4 | \usepackage{amsmath} 5 | 6 | \pagestyle{headings} 7 | \showboxdepth=0 8 | \makeindex 9 | \input{commands} 10 | 11 | \def\headertitle{Revised$^{7}$ Scheme} 12 | \def\integerversion{7} 13 | 14 | % Sizes and dimensions 15 | 16 | \topmargin -.375in % Nominal distance from top of page to top of 17 | % box containing running head. 18 | \headsep 15pt % Space between running head and text. 19 | 20 | \textheight 663pt % Height of text (including footnotes and figures, 21 | % excluding running head and foot). 22 | 23 | \textwidth 523pt % Width of text line. 24 | \columnsep 15pt % Space between columns 25 | \columnseprule 0pt % Width of rule between columns. 26 | 27 | \parskip 5pt plus 2pt minus 2pt % Extra vertical space between paragraphs. 28 | \parindent 0pt % Width of paragraph indentation. 29 | \topsep 0pt plus 2pt % Extra vertical space, in addition to 30 | % \parskip, added above and below list and 31 | % paragraphing environments. 32 | 33 | \oddsidemargin -.5in % Left margin on odd-numbered pages. 34 | \evensidemargin -.5in % Left margin on even-numbered pages. 35 | 36 | %% End of sizes and dimensions 37 | 38 | \usepackage{hyperref} 39 | %% \usepackage{supertabular} 40 | 41 | \begin{document} 42 | 43 | \parindent 0pt %!! 15pt % Width of paragraph indentation. 44 | 45 | % First page 46 | 47 | \thispagestyle{empty} 48 | 49 | 50 | \topnewpage[{ 51 | \begin{center} {\huge\bf 52 | 修订{\Huge$^{\mathbf{7}}$} 算法语言概述 \\ 53 | \vskip 3pt 54 | Scheme} 55 | 56 | \vskip 1ex 57 | $$ 58 | \begin{tabular}{l@{\extracolsep{.5in}}l@{\extracolsep{.5in}}l} 59 | \multicolumn{3}{c}{A\authorsc{LEX} S\authorsc{HINN}, 60 | J\authorsc{OHN} C\authorsc{OWAN}, \authorsc{AND} 61 | A\authorsc{RTHUR} A. G\authorsc{LECKLER} (\textit{Editors})} \\ 62 | \\ 63 | S\authorsc{TEVEN} G\authorsc{ANZ} & 64 | A\authorsc{LEXEY} R\authorsc{ADUL} & 65 | O\authorsc{LIN} S\authorsc{HIVERS} \\ 66 | 67 | A\authorsc{ARON} W. H\authorsc{SU} & 68 | J\authorsc{EFFREY} T. R\authorsc{EAD} & 69 | A\authorsc{LARIC} S\authorsc{NELL}-P\authorsc{YM} \\ 70 | 71 | B\authorsc{RADLEY} L\authorsc{UCIER} & 72 | D\authorsc{AVID} R\authorsc{USH} & 73 | G\authorsc{ERALD} J. S\authorsc{USSMAN} \\ 74 | 75 | E\authorsc{MMANUEL} M\authorsc{EDERNACH} & 76 | B\authorsc{ENJAMIN} L. R\authorsc{USSEL} & 77 | \\ 78 | \\ 79 | \multicolumn{3}{c}{R\authorsc{ICHARD} K\authorsc{ELSEY}, 80 | W\authorsc{ILLIAM} C\authorsc{LINGER}, 81 | \authorsc{AND} J\authorsc{ONATHAN} R\authorsc{EES}} \\ 82 | \multicolumn{3}{c}{\textit{(Editors, Revised$^{\mathit{5}}$ Report on the Algorithmic Language Scheme)}} \\ 83 | \\ 84 | \multicolumn{3}{c}{M\authorsc{ICHAEL} S\authorsc{PERBER}, 85 | R. K\authorsc{ENT} D\authorsc{YBVIG}, M\authorsc{ATTHEW} F\authorsc{LATT}, 86 | \authorsc{AND} A\authorsc{NTON} \authorsc{VAN} S\authorsc{TRAATEN}} \\ 87 | \multicolumn{3}{c}{\textit{(Editors, Revised$^{\mathit{6}}$ Report on the Algorithmic Language Scheme)}} \\ 88 | \end{tabular} 89 | $$ 90 | \vskip 2ex 91 | {\it 献给对John McCarthy 和 Daniel Weinreb的记忆} 92 | \vskip 2.6ex 93 | \end{center} 94 | }] 95 | 96 | \clearpage 97 | 98 | \eject 99 | \input{overview-body} \par 100 | 101 | \vfill\eject 102 | 103 | 104 | 105 | \end{document} 106 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/DatumRecord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | import java.util.*; 19 | /** 20 | * A data structure being used to trace cyclic reference. Mainly for internal use. 21 | * @author Chan Chung Kwong <1m02math@126.com> 22 | */ 23 | public class DatumRecord{ 24 | private static int idCounter=0; 25 | private final int id; 26 | private boolean reused,defined; 27 | /** 28 | * Construct a record 29 | */ 30 | public DatumRecord(){ 31 | this.id=++idCounter; 32 | this.reused=false; 33 | this.defined=false; 34 | } 35 | /** 36 | * Mark the record as reused 37 | */ 38 | public void reuse(){ 39 | reused=true; 40 | } 41 | /** 42 | * Check if the record is marked as reused 43 | * @return 44 | */ 45 | public boolean isReused(){ 46 | return reused; 47 | } 48 | /** 49 | * Mark the record as defined 50 | */ 51 | public void define(){ 52 | defined=true; 53 | } 54 | /** 55 | * Check if the record is marked as defined 56 | * @return 57 | */ 58 | public boolean isDefined(){ 59 | return defined; 60 | } 61 | /** 62 | * Get the ID of the record 63 | * @return 64 | */ 65 | public int getId(){ 66 | return id; 67 | } 68 | /** 69 | * Ensure that new records have a greater ID later on 70 | * @param counter 71 | */ 72 | public static void updateId(int counter){ 73 | if(counter>idCounter) 74 | idCounter=counter; 75 | } 76 | @Override 77 | public String toString(){ 78 | return super.toString(); 79 | } 80 | /** 81 | * Collect reference in a object to a map 82 | * @param object 83 | * @param map 84 | */ 85 | public static void collectReference(ScmObject object,IdentityHashMap map){ 86 | if(map.containsKey(object)) 87 | map.get(object).reuse(); 88 | else if(object instanceof ScmVector){ 89 | map.put(object,new DatumRecord()); 90 | for(int i=0;i<((ScmVector)object).getLength();i++) 91 | collectReference(((ScmVector)object).get(i),map); 92 | }else if(object instanceof ScmPair){ 93 | map.put(object,new DatumRecord()); 94 | collectReference(((ScmPair)object).getCar(),map); 95 | collectReference(((ScmPair)object).getCdr(),map); 96 | } 97 | } 98 | /** 99 | * Write external representation of a object 100 | * @param obj the object 101 | * @param buf output buffer 102 | * @param refs known references 103 | * @return 104 | */ 105 | public static boolean toExternalRepresentation(ScmObject obj,StringBuilder buf,IdentityHashMap refs){ 106 | if(obj instanceof ScmVector){ 107 | return ((ScmVector)obj).toExternalRepresentation(buf,refs); 108 | }else if(obj instanceof ScmPair){ 109 | return ((ScmPair)obj).toExternalRepresentation(buf,refs); 110 | }else{ 111 | buf.append(obj.toExternalRepresentation()); 112 | return true; 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /doc/extract.scm: -------------------------------------------------------------------------------- 1 | 2 | ; Code to extract the examples from the report. Written for R5RS by 3 | ; Richard Kelsey. 4 | 5 | ; This prints everything in INPUT-FILE that is between a "\begin{scheme}" 6 | ; and an "\end{scheme}" to the current output port. 7 | 8 | (define (find-examples input-file) 9 | (call-with-input-file input-file 10 | (lambda (in) 11 | (extract-text "\\begin{scheme}" 12 | "\\end{scheme}" 13 | (input-port->source in) 14 | (output-port->sink (current-output-port)))))) 15 | 16 | ; Turning ports into sources (thunks that generate characters) and 17 | ; sinks (procedures of one argument that consume characters). 18 | 19 | (define (input-port->source port) 20 | (lambda () 21 | (read-char port))) 22 | 23 | (define (output-port->sink port) 24 | (lambda (char) 25 | (write-char char port))) 26 | 27 | ; Read characters from SOURCE, passing to SINK all characters found between 28 | ; the strings BEGIN and END. 29 | 30 | (define (extract-text begin end source sink) 31 | (let loop () 32 | (if (find-string begin source (lambda (char) (values))) 33 | (if (find-string end source sink) 34 | (loop))))) 35 | 36 | ; Transfer characters from SOURCE to SINK until STRING is found. 37 | ; 38 | ; We first make a circular buffer containing the first (string-length STRING) 39 | ; characters from SOURCE. We then compare the buffer with STRING to see if 40 | ; a match is found. If not, we pass the first character from the buffer to 41 | ; SINK and get the next item from SOURCE. If it's a character we put it in 42 | ; the buffer, advance the buffer one character, and continue. When we reach 43 | ; the end of SOURCE, the remaining characters in the buffer are passed to SINK. 44 | 45 | (define (find-string string source sink) 46 | (let ((buffer (make-circular-buffer (string-length string) source))) 47 | (let loop ((buffer buffer)) 48 | (if (buffer-match? string buffer) 49 | #t 50 | (begin 51 | (sink (car buffer)) 52 | (let ((next (source))) 53 | (if (char? next) 54 | (begin 55 | (set-car! buffer next) 56 | (loop (cdr buffer))) 57 | (begin 58 | (set-car! buffer #f) 59 | (let flush-loop ((buffer (cdr buffer))) 60 | (if (car buffer) 61 | (begin 62 | (sink (car buffer)) 63 | (flush-loop (cdr buffer))) 64 | #f)))))))))) 65 | 66 | ; Returns a circular list of COUNT pairs containing the first COUNT 67 | ; items from SOURCE. 68 | 69 | (define (make-circular-buffer count source) 70 | (let ((start (list (source)))) 71 | (let loop ((last start) (i 1)) 72 | (if (= i count) 73 | (begin 74 | (set-cdr! last start) 75 | last) 76 | (let ((next (list (source)))) 77 | (set-cdr! last next) 78 | (loop next (+ i 1))))) 79 | start)) 80 | 81 | ; Returns #T if the contents of the BUFFER, a list of characters, matches 82 | ; STRING. This is the same as `(string=? string (list->string buffer))' 83 | ; except that it works for circular buffers. 84 | 85 | (define (buffer-match? string buffer) 86 | (let loop ((buffer buffer) (i 0)) 87 | (cond ((= i (string-length string)) 88 | #t) 89 | ((char=? (car buffer) (string-ref string i)) 90 | (loop (cdr buffer) (+ i 1))) 91 | (else 92 | #f)))) 93 | 94 | ; Return a source that generates the characters from STRING. This is only 95 | ; used for testing. 96 | 97 | (define (string-source string) 98 | (let ((i 0)) 99 | (lambda () 100 | (if (= i (string-length string)) 101 | #f 102 | (begin 103 | (set! i (+ i 1)) 104 | (string-ref string (- i 1))))))) 105 | 106 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/Char.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.car; 20 | import com.github.chungkwong.jschememin.type.*; 21 | /** 22 | * Correspoding to the library (scheme char) in Scheme 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class Char extends NativeLibrary{ 26 | public static final Char INSTANCE=new Char(); 27 | private Char(){ 28 | super("scheme","char"); 29 | } 30 | @Override 31 | protected void init(Library lib){ 32 | addNativeProcedure("char-alphabetic?",(o)->ScmBoolean.valueOf(((ScmCharacter)car(o)).isAlphabetic())); 33 | addNativeProcedure("char-numeric?",(o)->ScmBoolean.valueOf(((ScmCharacter)car(o)).isNumeric())); 34 | addNativeProcedure("char-whitespace?",(o)->ScmBoolean.valueOf(((ScmCharacter)car(o)).isWhiteSpace())); 35 | addNativeProcedure("char-upper-case?",(o)->ScmBoolean.valueOf(((ScmCharacter)car(o)).isUpperCase())); 36 | addNativeProcedure("char-lower-case?",(o)->ScmBoolean.valueOf(((ScmCharacter)car(o)).isLowerCase())); 37 | addNativeProcedure("digit-value",(o)->{int d=((ScmCharacter)car(o)).getDigitValue();return d>=0?new ScmInteger(d):ScmBoolean.FALSE;}); 38 | addNativeProcedure("char-upcase",(o)->((ScmCharacter)car(o)).upCase()); 39 | addNativeProcedure("char-downcase",(o)->((ScmCharacter)car(o)).downCase()); 40 | addNativeProcedure("char-foldcase",(o)->((ScmCharacter)car(o)).foldCase()); 41 | addNativeProcedure("string-upcase",(o)->((ScmString)car(o)).toUpperCase()); 42 | addNativeProcedure("string-downcase",(o)->((ScmString)car(o)).toLowerCase()); 43 | addNativeProcedure("string-foldcase",(o)->((ScmString)car(o)).toFoldingCase()); 44 | addNativeProcedure("char-ci=?",Utility.chainComparator((a,b)->((ScmCharacter)a).compareToIgnoreCase((ScmCharacter)b)==0)); 45 | addNativeProcedure("char-ci((ScmCharacter)a).compareToIgnoreCase((ScmCharacter)b)<0)); 46 | addNativeProcedure("char-ci<=?",Utility.chainComparator((a,b)->((ScmCharacter)a).compareToIgnoreCase((ScmCharacter)b)<=0)); 47 | addNativeProcedure("char-ci>?",Utility.chainComparator((a,b)->((ScmCharacter)a).compareToIgnoreCase((ScmCharacter)b)>0)); 48 | addNativeProcedure("char-ci>=?",Utility.chainComparator((a,b)->((ScmCharacter)a).compareToIgnoreCase((ScmCharacter)b)>=0)); 49 | addNativeProcedure("string-ci=?",Utility.chainComparator((a,b)->((ScmString)a).compareToIgnoreCase((ScmString)b)==0)); 50 | addNativeProcedure("string-ci((ScmString)a).compareToIgnoreCase((ScmString)b)<0)); 51 | addNativeProcedure("string-ci<=?",Utility.chainComparator((a,b)->((ScmString)a).compareToIgnoreCase((ScmString)b)<=0)); 52 | addNativeProcedure("string-ci>?",Utility.chainComparator((a,b)->((ScmString)a).compareToIgnoreCase((ScmString)b)>0)); 53 | addNativeProcedure("string-ci>=?",Utility.chainComparator((a,b)->((ScmString)a).compareToIgnoreCase((ScmString)b)>=0)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/HashTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import static com.github.chungkwong.jschememin.lib.Utility.caddr; 20 | import static com.github.chungkwong.jschememin.lib.Utility.cadr; 21 | import static com.github.chungkwong.jschememin.lib.Utility.car; 22 | import com.github.chungkwong.jschememin.type.*; 23 | /** 24 | * Correspoding to the library (scheme hashtables) in Scheme 25 | * @author Chan Chung Kwong <1m02math@126.com> 26 | */ 27 | public class HashTable extends NativeLibrary{ 28 | private static final ScmSymbol OK=new ScmSymbol("ok"); 29 | public static final HashTable INSTANCE=new HashTable(); 30 | private HashTable(){ 31 | super("scheme","hashtables"); 32 | } 33 | @Override 34 | protected void init(Library lib){ 35 | addNativeProcedure("make-hashtable",new NativeProcedureDefault( 36 | (o)->new ScmHashTable((Evaluable)car(o),(Evaluable)cadr(o),((ScmComplex)caddr(o)).intValueExact()), 37 | (o)->car(o),(o)->cadr(o),(o)->new ScmInteger(16))); 38 | addNativeProcedure("hashtable-copy",new NativeProcedureDefault( 39 | (o)->((ScmHashTable)car(o)).copy(((ScmBoolean)cadr(o)).isTrue()), 40 | (o)->car(o),(o)->ScmBoolean.FALSE)); 41 | addNativeProcedure("hashtable-mutable?",(o)->ScmBoolean.valueOf(((ScmHashTable)car(o)).isMutable())); 42 | addNativeProcedure("hashtable-equivalence-function",(o)->((ScmHashTable)car(o)).getEquivalenceFunction()); 43 | addNativeProcedure("hashtable-hash-function",(o)->((ScmHashTable)car(o)).getHashFunction()); 44 | addNativeProcedure("hashtable?",(o)->ScmBoolean.valueOf(car(o)instanceof ScmHashTable)); 45 | addNativeProcedure("hashtable-contains?",(o)->ScmBoolean.valueOf(((ScmHashTable)car(o)).contains(cadr(o)))); 46 | addNativeProcedure("hashtable-size",(o)->new ScmInteger(((ScmHashTable)car(o)).size())); 47 | addNativeProcedure("hashtable-ref",(o)->((ScmHashTable)car(o)).get(cadr(o),caddr(o))); 48 | addNativeProcedure("hashtable-set!",(o)->{((ScmHashTable)car(o)).put(cadr(o),caddr(o));return OK;}); 49 | addNativeProcedure("hashtable-delete!",(o)->{((ScmHashTable)car(o)).remove(cadr(o));return OK;}); 50 | addNativeProcedure("hashtable-clear!",(o)->{((ScmHashTable)car(o)).clear();return OK;}); 51 | addNativeProcedure("hashtable-keys",(o)->((ScmHashTable)car(o)).keys()); 52 | addNativeProcedureMulti("hashtable-entries",(o)->ScmList.toList(((ScmHashTable)car(o)).keys(),((ScmHashTable)car(o)).values())); 53 | addNativeProcedure("equal-hash",(o)->new ScmInteger(((ScmObject)car(o)).hashCode())); 54 | addNativeProcedure("string-hash",(o)->new ScmInteger(((ScmString)car(o)).hashCode())); 55 | addNativeProcedure("string-ci-hash",(o)->new ScmInteger(((ScmString)car(o)).toFoldingCase().hashCode())); 56 | addNativeProcedure("symbol-hash",(o)->new ScmInteger(((ScmSymbol)car(o)).hashCode())); 57 | addDeriveFile("/com/github/chungkwong/jschememin/lib/hashtables_derive.scm", 58 | "make-eq-hashtable","make-eqv-hashtable","hashtable-update!"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | /** 19 | * Represents errors in Scheme 20 | * @author Chan Chung Kwong <1m02math@126.com> 21 | */ 22 | public class ScmError extends ScmObject{ 23 | /** 24 | * The type of error in Scheme 25 | */ 26 | public static enum ErrorType{ 27 | READ,FILE,SYNTAX,JAVA,OTHER 28 | } 29 | private final ScmString message; 30 | private final ScmPairOrNil irritants; 31 | private final ErrorType type; 32 | /** 33 | * Construct a error 34 | * @param message the error message 35 | * @param irritants something related to the errir 36 | * @param type the type of the error 37 | */ 38 | public ScmError(ScmString message,ScmPairOrNil irritants,ErrorType type){ 39 | this.message=message; 40 | this.irritants=irritants; 41 | this.type=type; 42 | } 43 | 44 | /** 45 | * Get the error message 46 | * @return 47 | */ 48 | public ScmString getErrorMessage(){ 49 | return message; 50 | } 51 | /** 52 | * Get something related to the error 53 | * @return 54 | */ 55 | public ScmPairOrNil getIrritants(){ 56 | return irritants; 57 | } 58 | /** 59 | * Get the type of the error 60 | * @return 61 | */ 62 | public ErrorType getType(){ 63 | return type; 64 | } 65 | @Override 66 | public String toExternalRepresentation(){ 67 | return new ScmPair(new ScmSymbol("error"),new ScmPair(message,irritants)).toExternalRepresentation(); 68 | } 69 | @Override 70 | public boolean isSelfevaluating(){ 71 | return true; 72 | } 73 | /** 74 | * Wrap a Throwable 75 | * @param t 76 | * @return 77 | */ 78 | public static RuntimeException toRuntimeException(Throwable t){ 79 | if(t instanceof ScmException) 80 | return (ScmException)t; 81 | return new ScmException(toScmObject(t)); 82 | } 83 | /** 84 | * Wrap a error object 85 | * @param obj 86 | * @return 87 | */ 88 | public static RuntimeException toException(ScmObject obj){ 89 | if(obj instanceof ScmError&&((ScmError)obj).getType()==ErrorType.JAVA) 90 | return new ScmException(obj,(Throwable)((ScmJavaObject)ScmList.first(((ScmError)obj).getIrritants())).getJavaObject()); 91 | else 92 | return new ScmException(obj); 93 | } 94 | /** 95 | * Convert to a Scheme object 96 | * @param obj 97 | * @return 98 | */ 99 | public static ScmObject toScmObject(Throwable obj){ 100 | //obj.printStackTrace(); 101 | if(obj instanceof ScmException) 102 | return ((ScmException)obj).getObject(); 103 | return new ScmError(new ScmString(obj.toString()),ScmList.toList(new ScmJavaObject(obj)),ErrorType.JAVA); 104 | } 105 | private static class ScmException extends RuntimeException{ 106 | private final ScmObject obj; 107 | public ScmException(ScmObject obj){ 108 | super(); 109 | this.obj=obj; 110 | } 111 | public ScmException(ScmObject obj,Throwable cause){ 112 | super(cause); 113 | this.obj=obj; 114 | } 115 | public ScmObject getObject(){ 116 | return obj; 117 | } 118 | @Override 119 | public String getMessage(){ 120 | return obj.toExternalRepresentation(); 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/primitive/Import.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.primitive; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | import java.util.*; 21 | /** 22 | * Correspoding to the primitive import in Scheme 23 | * @author Chan Chung Kwong <1m02math@126.com> 24 | */ 25 | public class Import extends BasicConstruct implements Primitive{ 26 | public static final Import INSTANCE=new Import(); 27 | private static final ScmSymbol PREFIX=new ScmSymbol("prefix"); 28 | private static final ScmSymbol RENAME=new ScmSymbol("rename"); 29 | private static final ScmSymbol EXCEPT=new ScmSymbol("except"); 30 | private static final ScmSymbol ONLY=new ScmSymbol("only"); 31 | private Import(){ 32 | super(new ScmSymbol("import")); 33 | } 34 | @Override 35 | public void call(SchemeEnvironment env,Continuation cont,Object pointer,ScmPairOrNil list){ 36 | importLibraries(env,list); 37 | cont.ret(new ScmSymbol("ok")); 38 | } 39 | public SchemeEnvironment importLibraries(SchemeEnvironment env,ScmObject list){ 40 | ScmList.forEach(list,(o)->importLibrary(env,(ScmPair)o)); 41 | return env; 42 | } 43 | private void importLibrary(SchemeEnvironment env,ScmPair spec){ 44 | ImportSet set=getImportSet(spec); 45 | set.lib.exportTo(env,set.ex2im); 46 | } 47 | private ImportSet getImportSet(ScmPair list){ 48 | if(list.getCdr() instanceof ScmPair&&((ScmPair)list.getCdr()).getCar() instanceof ScmPair){ 49 | ScmObject car=list.getCar(); 50 | ImportSet set=getImportSet((ScmPair)list.getCadr()); 51 | list=(ScmPair)list.getCddr(); 52 | if(car.equals(PREFIX)){ 53 | ScmSymbol prefix=(ScmSymbol)list.getCar(); 54 | for(Map.Entry entry:set.ex2im.entrySet()){ 55 | entry.setValue(new ScmSymbol(prefix.getValue()+entry.getValue().getValue())); 56 | } 57 | }else if(car.equals(RENAME)){ 58 | HashMap rename=new HashMap<>(); 59 | ScmList.forEach(list,(c)->rename.put((ScmSymbol)((ScmPair)c).getCar(),(ScmSymbol)((ScmPair)c).getCadr())); 60 | for(Map.Entry entry:set.ex2im.entrySet()) 61 | if(rename.containsKey(entry.getValue())) 62 | entry.setValue(rename.get(entry.getValue())); 63 | }else if(car.equals(EXCEPT)){ 64 | HashSet remain=new HashSet<>(); 65 | ScmList.forEach(list,(c)->remain.add((ScmSymbol)c)); 66 | Iterator> iter=set.ex2im.entrySet().iterator(); 67 | while(iter.hasNext()) 68 | if(remain.contains(iter.next().getValue())) 69 | iter.remove(); 70 | }else if(car.equals(ONLY)){ 71 | HashSet remain=new HashSet<>(); 72 | ScmList.forEach(list,(c)->remain.add((ScmSymbol)c)); 73 | Iterator> iter=set.ex2im.entrySet().iterator(); 74 | while(iter.hasNext()) 75 | if(!remain.contains(iter.next().getValue())) 76 | iter.remove(); 77 | } 78 | return set; 79 | }else 80 | return new ImportSet(list); 81 | } 82 | static class ImportSet{ 83 | final Library lib; 84 | final HashMap ex2im=new HashMap<>(); 85 | public ImportSet(ScmPair libName){ 86 | lib=LibraryManager.getLibrary(libName); 87 | lib.getExportSet().stream().forEach((exportName)->{ 88 | ex2im.put(exportName,exportName); 89 | }); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/lib/NativeLibrary.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.lib; 18 | import com.github.chungkwong.jschememin.*; 19 | import com.github.chungkwong.jschememin.type.*; 20 | import java.io.*; 21 | import java.util.*; 22 | import java.util.logging.*; 23 | /** 24 | * Loader for native library 25 | * @author Chan Chung Kwong <1m02math@126.com> 26 | */ 27 | public abstract class NativeLibrary implements LibraryLoader{ 28 | private Library lib=null; 29 | private final ScmPair name; 30 | /** 31 | * 32 | * @param part the name of the library 33 | */ 34 | public NativeLibrary(String... part){ 35 | this.name=(ScmPair)Arrays.stream(part).map((n)->new ScmSymbol(n)).collect(ScmList.COLLECTOR); 36 | } 37 | @Override 38 | public ScmPair getName(){ 39 | return name; 40 | } 41 | @Override 42 | public Library getLibrary(){ 43 | if(lib==null){ 44 | lib=new Library(name,new HashMap<>(),new SchemeEnvironment(false)); 45 | init(lib); 46 | } 47 | return lib; 48 | } 49 | /** 50 | * Add a object into the library 51 | * @param name the variable name 52 | * @param obj the object 53 | * @param export if the object prefered to be exposed to users 54 | */ 55 | protected void addNative(ScmSymbol name,ScmObject obj,boolean export){ 56 | lib.getInternalEnvironment().add(name,obj); 57 | if(export) 58 | lib.getExportMap().put(name,name); 59 | } 60 | /** 61 | * Add a object into the library 62 | * @param type 63 | */ 64 | protected void addPrimitiveType(BasicConstruct type){ 65 | lib.getInternalEnvironment().addPrimitiveType(type); 66 | lib.getExportMap().put(type.getKeyword(),type.getKeyword()); 67 | } 68 | /** 69 | * Exexute a derive file and use add variables that it define to the library 70 | * @param file the file name 71 | * @param export the variable to be exposed to users 72 | */ 73 | protected void addDeriveFile(String file,String... export){ 74 | try{ 75 | Parser parser=new Parser(new Lex(new InputStreamReader(NativeLibrary.class.getResourceAsStream(file),"UTF-8"))); 76 | SchemeEnvironment internal=lib.getInternalEnvironment(); 77 | Evaluator evaluator=new Evaluator(internal); 78 | parser.getRemainingDatums().forEach((d)->evaluator.eval(d)); 79 | for(String name:export){ 80 | ScmSymbol id=new ScmSymbol(name); 81 | lib.getExportMap().put(id,id); 82 | } 83 | }catch(UnsupportedEncodingException ex){ 84 | Logger.getGlobal().log(Level.SEVERE,null,ex); 85 | } 86 | } 87 | /** 88 | * Add a object into the library 89 | * @param name the variable name 90 | * @param proc the object 91 | */ 92 | protected void addNativeProcedure(String name,NativeProcedure proc){ 93 | ScmSymbol sym=new ScmSymbol(name); 94 | lib.getInternalEnvironment().add(sym,new NativeEvaluable(proc)); 95 | lib.getExportMap().put(sym,sym); 96 | } 97 | /** 98 | * Add a object into the library 99 | * @param name the variable name 100 | * @param proc the object 101 | */ 102 | protected void addNativeProcedureMulti(String name,NativeProcedure proc){ 103 | ScmSymbol sym=new ScmSymbol(name); 104 | lib.getInternalEnvironment().add(sym,new NativeEvaluableMulti(proc)); 105 | lib.getExportMap().put(sym,sym); 106 | } 107 | /** 108 | * To be executed when the library actual being loaded 109 | * @param lib the library 110 | */ 111 | protected abstract void init(Library lib); 112 | } 113 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmPair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | import java.util.*; 19 | /** 20 | * Represents the type pair in Scheme 21 | * @author kwong 22 | */ 23 | public final class ScmPair extends ScmPairOrNil{ 24 | private ScmObject car; 25 | private ScmObject cdr; 26 | /** 27 | * Construct a pair 28 | * @param car the car field 29 | * @param cdr the cdr field 30 | */ 31 | public ScmPair(ScmObject car,ScmObject cdr){ 32 | this.car=car; 33 | this.cdr=cdr; 34 | } 35 | /** 36 | * Corresponding to the procedure car in Scheme 37 | * @return 38 | */ 39 | public ScmObject getCar(){ 40 | return car; 41 | } 42 | /** 43 | * Corresponding to the procedure cdr in Scheme 44 | * @return 45 | */ 46 | public ScmObject getCdr(){ 47 | return cdr; 48 | } 49 | public ScmObject getCaar(){ 50 | return ((ScmPair)car).getCar(); 51 | } 52 | public ScmObject getCadr(){ 53 | return ((ScmPair)cdr).getCar(); 54 | } 55 | public ScmObject getCdar(){ 56 | return ((ScmPair)car).getCdr(); 57 | } 58 | public ScmObject getCddr(){ 59 | return ((ScmPair)cdr).getCdr(); 60 | } 61 | public ScmObject getCaddr(){ 62 | return ((ScmPair)((ScmPair)cdr).getCdr()).getCar(); 63 | } 64 | /** 65 | * Corresponding to the procedure set-car! in Scheme 66 | * @param car 67 | */ 68 | public void setCar(ScmObject car){ 69 | this.car=car; 70 | } 71 | /** 72 | * Corresponding to the procedure set-cdr! in Scheme 73 | * @param cdr 74 | */ 75 | public void setCdr(ScmObject cdr){ 76 | this.cdr=cdr; 77 | } 78 | @Override 79 | public boolean equals(Object obj){ 80 | return obj==this||ObjectPair.equals(this,obj,new HashSet<>()); 81 | } 82 | @Override 83 | public boolean equalsValue(ScmObject obj){ 84 | return this==obj; 85 | } 86 | @Override 87 | public int hashCode(){ 88 | int hash=7; 89 | if(!(car instanceof ScmPair||car instanceof ScmVector)) 90 | hash=13*hash+Objects.hashCode(this.car); 91 | if(!(cdr instanceof ScmPair||cdr instanceof ScmVector)) 92 | hash=13*hash+Objects.hashCode(this.cdr); 93 | return hash; 94 | } 95 | @Override 96 | public String toExternalRepresentation(){ 97 | StringBuilder buf=new StringBuilder(); 98 | IdentityHashMap refs=new IdentityHashMap<>(); 99 | DatumRecord.collectReference(this,refs); 100 | toExternalRepresentation(buf,refs); 101 | return buf.toString(); 102 | } 103 | boolean toExternalRepresentation(StringBuilder buf,IdentityHashMap refs){ 104 | DatumRecord record=refs.get(this); 105 | if(record!=null&&record.isReused()){ 106 | if(record.isDefined()){ 107 | buf.append('#').append(record.getId()).append('#'); 108 | return false; 109 | }else{ 110 | buf.append('#').append(record.getId()).append('='); 111 | record.define(); 112 | } 113 | } 114 | buf.append("("); 115 | DatumRecord.toExternalRepresentation(car,buf,refs); 116 | ScmObject next=cdr; 117 | boolean noCycle=true; 118 | while(next instanceof ScmPair&&!refs.get(next).isReused()){ 119 | buf.append(" "); 120 | DatumRecord.toExternalRepresentation(((ScmPair)next).getCar(),buf,refs); 121 | next=((ScmPair)next).getCdr(); 122 | } 123 | if(!(next instanceof ScmNil)){ 124 | buf.append(" . "); 125 | DatumRecord.toExternalRepresentation(next,buf,refs); 126 | } 127 | buf.append(")"); 128 | return true; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /doc/example.tex: -------------------------------------------------------------------------------- 1 | 2 | \extrapart{Example} % -*- Mode: Lisp; Package: SCHEME; Syntax: Common-lisp -*- 3 | 4 | \nobreak 5 | The procedure {\cf integrate-system} integrates the system 6 | $$y_k^\prime = f_k(y_1, y_2, \ldots, y_n), \; k = 1, \ldots, n$$ 7 | of differential equations with the method of Runge-Kutta. 8 | 9 | The parameter {\tt system-derivative} is a function that takes a system 10 | state (a vector of values for the state variables $y_1, \ldots, y_n$) 11 | and produces a system derivative (the values $y_1^\prime, \ldots, 12 | y_n^\prime$). The parameter {\tt initial-state} provides an initial 13 | system state, and {\tt h} is an initial guess for the length of the 14 | integration step. 15 | 16 | The value returned by {\cf integrate-system} is an infinite stream of 17 | system states. 18 | 19 | \begin{schemenoindent} 20 | (define (integrate-system system-derivative 21 | initial-state 22 | h) 23 | (let ((next (runge-kutta-4 system-derivative h))) 24 | (letrec ((states 25 | (cons initial-state 26 | (delay (map-streams next 27 | states))))) 28 | states)))% 29 | \end{schemenoindent} 30 | 31 | The procedure {\cf runge-kutta-4} takes a function, {\tt f}, that produces a 32 | system derivative from a system state. It 33 | produces a function that takes a system state and 34 | produces a new system state. 35 | 36 | \begin{schemenoindent} 37 | (define (runge-kutta-4 f h) 38 | (let ((*h (scale-vector h)) 39 | (*2 (scale-vector 2)) 40 | (*1/2 (scale-vector (/ 1 2))) 41 | (*1/6 (scale-vector (/ 1 6)))) 42 | (lambda (y) 43 | ;; y is a system state 44 | (let* ((k0 (*h (f y))) 45 | (k1 (*h (f (add-vectors y (*1/2 k0))))) 46 | (k2 (*h (f (add-vectors y (*1/2 k1))))) 47 | (k3 (*h (f (add-vectors y k2))))) 48 | (add-vectors y 49 | (*1/6 (add-vectors k0 50 | (*2 k1) 51 | (*2 k2) 52 | k3))))))) 53 | 54 | (define (elementwise f) 55 | (lambda vectors 56 | (generate-vector 57 | (vector-length (car vectors)) 58 | (lambda (i) 59 | (apply f 60 | (map (lambda (v) (vector-ref v i)) 61 | vectors)))))) 62 | 63 | (define (generate-vector size proc) 64 | (let ((ans (make-vector size))) 65 | (letrec ((loop 66 | (lambda (i) 67 | (cond ((= i size) ans) 68 | (else 69 | (vector-set! ans i (proc i)) 70 | (loop (+ i 1))))))) 71 | (loop 0)))) 72 | 73 | (define add-vectors (elementwise +)) 74 | 75 | (define (scale-vector s) 76 | (elementwise (lambda (x) (* x s))))% 77 | \end{schemenoindent} 78 | 79 | The {\cf map-streams} procedure is analogous to {\cf map}: it applies its first 80 | argument (a procedure) to all the elements of its second argument (a 81 | stream). 82 | 83 | \begin{schemenoindent} 84 | (define (map-streams f s) 85 | (cons (f (head s)) 86 | (delay (map-streams f (tail s)))))% 87 | \end{schemenoindent} 88 | 89 | Infinite streams are implemented as pairs whose car holds the first 90 | element of the stream and whose cdr holds a promise to deliver the rest 91 | of the stream. 92 | 93 | \begin{schemenoindent} 94 | (define head car) 95 | (define (tail stream) 96 | (force (cdr stream)))% 97 | \end{schemenoindent} 98 | 99 | \bigskip 100 | The following illustrates the use of {\cf integrate-system} in 101 | integrating the system 102 | $$ C {dv_C \over dt} = -i_L - {v_C \over R}$$\nobreak 103 | $$ L {di_L \over dt} = v_C$$ 104 | which models a damped oscillator. 105 | 106 | \begin{schemenoindent} 107 | (define (damped-oscillator R L C) 108 | (lambda (state) 109 | (let ((Vc (vector-ref state 0)) 110 | (Il (vector-ref state 1))) 111 | (vector (- 0 (+ (/ Vc (* R C)) (/ Il C))) 112 | (/ Vc L))))) 113 | 114 | (define the-states 115 | (integrate-system 116 | (damped-oscillator 10000 1000 .001) 117 | '\#(1 0) 118 | .01))% 119 | \end{schemenoindent} 120 | 121 | -------------------------------------------------------------------------------- /src/com/github/chungkwong/jschememin/type/ScmBinaryInputPort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Chan Chung Kwong <1m02math@126.com> 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | package com.github.chungkwong.jschememin.type; 18 | import com.github.chungkwong.jschememin.*; 19 | import java.io.*; 20 | import java.math.*; 21 | import java.util.*; 22 | /** 23 | * Represents the type binary input port in Scheme 24 | * @author Chan Chung Kwong <1m02math@126.com> 25 | */ 26 | public class ScmBinaryInputPort extends ScmPort{ 27 | private final PushbackInputStream in; 28 | /** 29 | * Wrap a InputStream 30 | * @param in 31 | */ 32 | public ScmBinaryInputPort(PushbackInputStream in){ 33 | this.in=in; 34 | } 35 | /** 36 | * Wrap a InputStream 37 | * @param in 38 | */ 39 | public ScmBinaryInputPort(InputStream in){ 40 | this(new PushbackInputStream(in)); 41 | } 42 | /** 43 | * Construct a port to read from a file 44 | * @param file the file name 45 | */ 46 | public ScmBinaryInputPort(String file){ 47 | try{ 48 | this.in=new PushbackInputStream(new FileInputStream(Main.resolveFile(file))); 49 | }catch(FileNotFoundException ex){ 50 | throw ScmError.toException(new ScmError(new ScmString(ex.getLocalizedMessage()),ScmNil.NIL,ScmError.ErrorType.FILE)); 51 | } 52 | } 53 | /** 54 | * Corresponding to the procedure read-u8 in Scheme 55 | * @return 56 | * @throws IOException 57 | */ 58 | public ScmObject readByte() throws IOException{ 59 | int b=in.read(); 60 | return b==-1?ScmEndOfFileObject.INSTANCE:new ScmInteger(BigInteger.valueOf(b)); 61 | } 62 | /** 63 | * Corresponding to the procedure peek-u8 in Scheme 64 | * @return 65 | * @throws IOException 66 | */ 67 | public ScmObject peekByte() throws IOException{ 68 | int b=in.read(); 69 | if(b==-1) 70 | return ScmEndOfFileObject.INSTANCE; 71 | else{ 72 | in.unread(b); 73 | return new ScmInteger(BigInteger.valueOf(b)); 74 | } 75 | } 76 | /** 77 | * Corresponding to the procedure read-bytevector in Scheme 78 | * @param max 79 | * @return 80 | * @throws IOException 81 | */ 82 | public ScmObject readBytevector(ScmInteger max) throws IOException{ 83 | int len=max.getValue().intValueExact(); 84 | byte[] buf=new byte[len]; 85 | len=in.read(buf); 86 | return len==-1?ScmEndOfFileObject.INSTANCE:new ScmByteVector(Arrays.copyOf(buf,len)); 87 | } 88 | /** 89 | * Corresponding to the procedure read-bytevector in Scheme 90 | * @param vector 91 | * @param start 92 | * @param end 93 | * @return 94 | * @throws IOException 95 | */ 96 | public ScmObject readBytevector(ScmByteVector vector,ScmInteger start,ScmInteger end) throws IOException{ 97 | int offset=start.getValue().intValueExact(); 98 | int len=end.getValue().intValueExact()-offset; 99 | len=in.read(vector.getByteArray(),offset,len); 100 | return len==-1?ScmEndOfFileObject.INSTANCE:new ScmInteger(BigInteger.valueOf(len)); 101 | } 102 | /** 103 | * Corresponding to the procedure u8-ready in Scheme 104 | * @return 105 | * @throws IOException 106 | */ 107 | public ScmBoolean ready() throws IOException{ 108 | return ScmBoolean.valueOf(in.available()>=1); 109 | } 110 | /** 111 | * Corresponding to the procedure close-input-port in Scheme 112 | * @return 113 | * @throws IOException 114 | */ 115 | @Override 116 | public ScmBinaryInputPort close()throws IOException{ 117 | super.close(); 118 | in.close(); 119 | return this; 120 | } 121 | @Override 122 | public String toExternalRepresentation(){ 123 | return in.toString(); 124 | } 125 | } --------------------------------------------------------------------------------