Next: 4 Scheme関数定義の登録.SchemePrimitives.java
Up: ソフトウェア特論 講義資料 JavaによるScheme言語処理系: Jscheme
Previous: 2 Envionmentクラス
PrimitiveクラスはスーパクラスをProcedureクラスとした
クラスです.
Procedureクラスは以下のようになっています.
package jscheme;
/** @author Peter Norvig,
* peter@norvig.com http://www.norvig.com
* Copyright 1998 Peter Norvig,
* see http://www.norvig.com/license.html **/
public abstract class Procedure extends SchemeUtils {
String name = "anonymous procedure";
public String toString() {
return "{" + name + "}";
}
public abstract Object
apply(Scheme interpreter, Object args);
/** Coerces a Scheme object to a procedure. **/
static Procedure proc(Object x) {
if (x instanceof Procedure)
return (Procedure) x;
else
return proc(error("Not a procedure: "
+ stringify(x)));
}
}
Primitiveクラスは以下のようになっています.
charAtは,文字列の中でのある位置の文字を返します.
先頭の位置は0です.
try, finally構文は,try ブロック1 finally ブロック2という形で,ブロッ
ク1内で例外が起こった場合,ブロック2を実行してtryを抜けます.例外が
起こらない場合でも,ブロック2を実行します.common lispでも同様の構文
として,unwind-protectというものがあります.
> (unwind-protect
(progn (print 1) (/ 10 1) (print 2))
(print 3))
1
2
3
2
package jscheme;
import java.io.*;
/** A primitive is a procedure that is defined
* as part of the Scheme report,
* and is implemented in Java code.
* @author Peter Norvig, peter@norvig.com
* http://www.norvig.com
* Copyright 1998 Peter Norvig,
* see http://www.norvig.com/license.html **/
public class Primitive extends Procedure {
int minArgs;
int maxArgs;
int idNumber;
public Primitive(int id,
int minArgs, int maxArgs) {
this.idNumber = id;
this.minArgs = minArgs;
this.maxArgs = maxArgs;
}
private static final int EQ = 0, LT = 1, GT = 2,
GE = 3, LE = 4, ABS = 5, EOF_OBJECT = 6,
EQQ = 7, EQUALQ = 8, FORCE = 9,
CAR = 10, FLOOR = 11, CEILING = 12, CONS = 13,
DIVIDE= 14, LENGTH = 15, LIST = 16, LISTQ = 17,
APPLY = 18, MAX = 19, MIN = 20, MINUS = 21,
NEWLINE = 22, NOT = 23, NULLQ = 24, NUMBERQ = 25,
PAIRQ = 26, PLUS = 27, PROCEDUREQ = 28,
READ = 29, CDR = 30, ROUND = 31, SECOND = 32,
SYMBOLQ = 33, TIMES = 34, TRUNCATE = 35,
WRITE = 36, APPEND = 37, BOOLEANQ = 38,
SQRT = 39, EXPT = 40, REVERSE = 41, ASSOC = 42,
ASSQ = 43, ASSV = 44, MEMBER = 45, MEMQ = 46,
MEMV = 47, EQVQ = 48, LISTREF = 49, LISTTAIL = 50,
STRINQ = 51, MAKESTRING = 52, STRING = 53,
STRINGLENGTH = 54, STRINGREF = 55, STRINGSET = 56,
SUBSTRING = 57,
STRINGAPPEND = 58, STRINGTOLIST = 59,
LISTTOSTRING = 60, SYMBOLTOSTRING = 61,
STRINGTOSYMBOL = 62, EXP = 63, LOG = 64,
SIN = 65, COS = 66, TAN = 67, ACOS = 68,
ASIN = 69, ATAN = 70, NUMBERTOSTRING = 71,
STRINGTONUMBER = 72, CHARQ = 73,
CHARALPHABETICQ = 74, CHARNUMERICQ = 75,
CHARWHITESPACEQ = 76, CHARUPPERCASEQ = 77,
CHARLOWERCASEQ = 78, CHARTOINTEGER = 79,
INTEGERTOCHAR = 80, CHARUPCASE = 81,
CHARDOWNCASE = 82, STRINGQ = 83,
VECTORQ = 84, MAKEVECTOR = 85, VECTOR = 86,
VECTORLENGTH = 87, VECTORREF = 88, VECTORSET = 89,
LISTTOVECTOR = 90, MAP = 91, FOREACH = 92,
CALLCC = 93, VECTORTOLIST = 94, LOAD = 95,
DISPLAY = 96, INPUTPORTQ = 98,
CURRENTINPUTPORT = 99, OPENINPUTFILE = 100,
CLOSEINPUTPORT = 101, OUTPUTPORTQ = 103,
CURRENTOUTPUTPORT = 104, OPENOUTPUTFILE = 105,
CLOSEOUTPUTPORT = 106, READCHAR = 107,
PEEKCHAR = 108, EVAL = 109, QUOTIENT = 110,
REMAINDER = 111, MODULO = 112, THIRD = 113,
EOFOBJECTQ = 114, GCD = 115, LCM = 116,
CXR = 117, ODDQ = 118, EVENQ = 119, ZEROQ = 120,
POSITIVEQ = 121, NEGATIVEQ = 122,
CHARCMP = 123 /* to 127 */,
CHARCICMP = 128 /* to 132 */,
STRINGCMP = 133 /* to 137 */,
STRINGCICMP = 138 /* to 142 */,
EXACTQ = 143, INEXACTQ = 144, INTEGERQ = 145,
CALLWITHINPUTFILE = 146, CALLWITHOUTPUTFILE = 147
;
//////////////// Extensions ////////////////
static final int NEW = -1, CLASS = -2,
METHOD = -3, EXIT = -4, SETCAR = -5,
SETCDR = -6, TIMECALL = -11, MACROEXPAND = -12,
ERROR = -13, LISTSTAR = -14
;
public static Environment
installPrimitives(Environment env) {
int n = Integer.MAX_VALUE;
env
.defPrim("*", TIMES, 0, n)
.defPrim("*", TIMES, 0, n)
.defPrim("+", PLUS, 0, n)
.defPrim("-", MINUS, 1, n)
.defPrim("/", DIVIDE, 1, n)
.defPrim("<", LT, 2, n)
.defPrim("<=", LE, 2, n)
.defPrim("=", EQ, 2, n)
.defPrim(">", GT, 2, n)
.defPrim(">=", GE, 2, n)
.defPrim("abs", ABS, 1)
.defPrim("acos", ACOS, 1)
.defPrim("append", APPEND, 0, n)
.defPrim("apply", APPLY, 2, n)
.defPrim("asin", ASIN, 1)
.defPrim("assoc", ASSOC, 2)
.defPrim("assq", ASSQ, 2)
.defPrim("assv", ASSV, 2)
.defPrim("atan", ATAN, 1)
.defPrim("boolean?", BOOLEANQ, 1)
.defPrim("caaaar", CXR, 1)
.defPrim("caaadr", CXR, 1)
.defPrim("caaar", CXR, 1)
.defPrim("caadar", CXR, 1)
.defPrim("caaddr", CXR, 1)
.defPrim("caadr", CXR, 1)
.defPrim("caar", CXR, 1)
.defPrim("cadaar", CXR, 1)
.defPrim("cadadr", CXR, 1)
.defPrim("cadar", CXR, 1)
.defPrim("caddar", CXR, 1)
.defPrim("cadddr", CXR, 1)
.defPrim("caddr", THIRD, 1)
.defPrim("cadr", SECOND, 1)
.defPrim("call-with-current-continuation",
CALLCC, 1)
.defPrim("call-with-input-file",
CALLWITHINPUTFILE, 2)
.defPrim("call-with-output-file",
CALLWITHOUTPUTFILE, 2)
.defPrim("car", CAR, 1)
.defPrim("cdaaar", CXR, 1)
.defPrim("cdaadr", CXR, 1)
.defPrim("cdaar", CXR, 1)
.defPrim("cdadar", CXR, 1)
.defPrim("cdaddr", CXR, 1)
.defPrim("cdadr", CXR, 1)
.defPrim("cdar", CXR, 1)
.defPrim("cddaar", CXR, 1)
.defPrim("cddadr", CXR, 1)
.defPrim("cddar", CXR, 1)
.defPrim("cdddar", CXR, 1)
.defPrim("cddddr", CXR, 1)
.defPrim("cdddr", CXR, 1)
.defPrim("cddr", CXR, 1)
.defPrim("cdr", CDR, 1)
.defPrim("char->integer",
CHARTOINTEGER, 1)
.defPrim("char-alphabetic?",
CHARALPHABETICQ, 1)
.defPrim("char-ci<=?", CHARCICMP+LE, 2)
.defPrim("char-ci<?" , CHARCICMP+LT, 2)
.defPrim("char-ci=?" , CHARCICMP+EQ, 2)
.defPrim("char-ci>=?", CHARCICMP+GE, 2)
.defPrim("char-ci>?" , CHARCICMP+GT, 2)
.defPrim("char-downcase", CHARDOWNCASE, 1)
.defPrim("char-lower-case?",
CHARLOWERCASEQ, 1)
.defPrim("char-numeric?", CHARNUMERICQ, 1)
.defPrim("char-upcase", CHARUPCASE, 1)
.defPrim("char-upper-case?",
CHARUPPERCASEQ, 1)
.defPrim("char-whitespace?",
CHARWHITESPACEQ, 1)
.defPrim("char<=?", CHARCMP+LE, 2)
.defPrim("char<?", CHARCMP+LT, 2)
.defPrim("char=?", CHARCMP+EQ, 2)
.defPrim("char>=?", CHARCMP+GE, 2)
.defPrim("char>?", CHARCMP+GT, 2)
.defPrim("char?", CHARQ, 1)
.defPrim("close-input-port",
CLOSEINPUTPORT, 1)
.defPrim("close-output-port",
CLOSEOUTPUTPORT, 1)
.defPrim("complex?", NUMBERQ, 1)
.defPrim("cons", CONS, 2)
.defPrim("cos", COS, 1)
.defPrim("current-input-port",
CURRENTINPUTPORT, 0)
.defPrim("current-output-port",
CURRENTOUTPUTPORT, 0)
.defPrim("display", DISPLAY, 1, 2)
.defPrim("eof-object?", EOFOBJECTQ, 1)
.defPrim("eq?", EQQ, 2)
.defPrim("equal?", EQUALQ, 2)
.defPrim("eqv?", EQVQ, 2)
.defPrim("eval", EVAL, 1, 2)
.defPrim("even?", EVENQ, 1)
.defPrim("exact?", INTEGERQ, 1)
.defPrim("exp", EXP, 1)
.defPrim("expt", EXPT, 2)
.defPrim("force", FORCE, 1)
.defPrim("for-each", FOREACH, 1, n)
.defPrim("gcd", GCD, 0, n)
.defPrim("inexact?", INEXACTQ, 1)
.defPrim("input-port?", INPUTPORTQ, 1)
.defPrim("integer->char",
INTEGERTOCHAR, 1)
.defPrim("integer?", INTEGERQ, 1)
.defPrim("lcm", LCM, 0, n)
.defPrim("length", LENGTH, 1)
.defPrim("list", LIST, 0, n)
.defPrim("list->string", LISTTOSTRING, 1)
.defPrim("list->vector", LISTTOVECTOR, 1)
.defPrim("list-ref", LISTREF, 2)
.defPrim("list-tail", LISTTAIL, 2)
.defPrim("list?", LISTQ, 1)
.defPrim("load", LOAD, 1)
.defPrim("log", LOG, 1)
.defPrim("macro-expand", MACROEXPAND,1)
.defPrim("make-string", MAKESTRING,1, 2)
.defPrim("make-vector", MAKEVECTOR,1, 2)
.defPrim("map", MAP, 1, n)
.defPrim("max", MAX, 1, n)
.defPrim("member", MEMBER, 2)
.defPrim("memq", MEMQ, 2)
.defPrim("memv", MEMV, 2)
.defPrim("min", MIN, 1, n)
.defPrim("modulo", MODULO, 2)
.defPrim("negative?", NEGATIVEQ, 1)
.defPrim("newline", NEWLINE, 0, 1)
.defPrim("not", NOT, 1)
.defPrim("null?", NULLQ, 1)
.defPrim("number->string",
NUMBERTOSTRING, 1, 2)
.defPrim("number?", NUMBERQ, 1)
.defPrim("odd?", ODDQ, 1)
.defPrim("open-input-file",
OPENINPUTFILE, 1)
.defPrim("open-output-file",
OPENOUTPUTFILE, 1)
.defPrim("output-port?",
OUTPUTPORTQ, 1)
.defPrim("pair?", PAIRQ, 1)
.defPrim("peek-char", PEEKCHAR, 0, 1)
.defPrim("positive?", POSITIVEQ, 1)
.defPrim("procedure?", PROCEDUREQ,1)
.defPrim("quotient", QUOTIENT, 2)
.defPrim("rational?", INTEGERQ, 1)
.defPrim("read", READ, 0, 1)
.defPrim("read-char", READCHAR, 0, 1)
.defPrim("real?", NUMBERQ, 1)
.defPrim("remainder", REMAINDER, 2)
.defPrim("reverse", REVERSE, 1)
.defPrim("round", ROUND, 1)
.defPrim("set-car!", SETCAR, 2)
.defPrim("set-cdr!", SETCDR, 2)
.defPrim("sin", SIN, 1)
.defPrim("sqrt", SQRT, 1)
.defPrim("string", STRING, 0, n)
.defPrim("string->list", STRINGTOLIST, 1)
.defPrim("string->number",
STRINGTONUMBER, 1, 2)
.defPrim("string->symbol",
STRINGTOSYMBOL, 1)
.defPrim("string-append",
STRINGAPPEND, 0, n)
.defPrim("string-ci<=?",
STRINGCICMP+LE, 2)
.defPrim("string-ci<?" ,
STRINGCICMP+LT, 2)
.defPrim("string-ci=?" ,
STRINGCICMP+EQ, 2)
.defPrim("string-ci>=?",
STRINGCICMP+GE, 2)
.defPrim("string-ci>?" ,
STRINGCICMP+GT, 2)
.defPrim("string-length",
STRINGLENGTH, 1)
.defPrim("string-ref",
STRINGREF, 2)
.defPrim("string-set!", STRINGSET, 3)
.defPrim("string<=?", STRINGCMP+LE, 2)
.defPrim("string<?", STRINGCMP+LT, 2)
.defPrim("string=?", STRINGCMP+EQ, 2)
.defPrim("string>=?", STRINGCMP+GE, 2)
.defPrim("string>?", STRINGCMP+GT, 2)
.defPrim("string?", STRINGQ, 1)
.defPrim("substring", SUBSTRING, 3)
.defPrim("symbol->string",
SYMBOLTOSTRING, 1)
.defPrim("symbol?", SYMBOLQ, 1)
.defPrim("tan", TAN, 1)
.defPrim("vector", VECTOR, 0, n)
.defPrim("vector->list",
VECTORTOLIST, 1)
.defPrim("vector-length",
VECTORLENGTH, 1)
.defPrim("vector-ref", VECTORREF, 2)
.defPrim("vector-set!", VECTORSET, 3)
.defPrim("vector?", VECTORQ, 1)
.defPrim("write", WRITE, 1, 2)
.defPrim("write-char", DISPLAY, 1, 2)
.defPrim("zero?", ZEROQ, 1)
///////////// Extensions ////////////////
.defPrim("new", NEW, 1)
.defPrim("class", CLASS, 1)
.defPrim("method", METHOD, 2, n)
.defPrim("exit", EXIT, 0, 1)
.defPrim("error", ERROR, 0, n)
.defPrim("time-call", TIMECALL, 1, 2)
.defPrim("_list*", LISTSTAR, 0, n)
;
return env;
}
/** Apply a primitive to a list of
arguments. **/
public Object apply(Scheme interp,
Object args) {
//First make sure there are the
// right number of arguments.
int nArgs = length(args);
if (nArgs < minArgs)
return error("too few args, " + nArgs +
", for " + this.name + ": " + args);
else if (nArgs > maxArgs)
return error("too many args, " + nArgs +
", for " + this.name + ": " + args);
Object x = first(args);
Object y = second(args);
switch (idNumber) {
///// SECTION 6.1 BOOLEANS
case NOT: return truth(x == FALSE);
case BOOLEANQ: return truth(x == TRUE ||
x == FALSE);
///// SECTION 6.2 EQUIVALENCE PREDICATES
case EQVQ: return truth(eqv(x, y));
case EQQ: return truth(x == y);
case EQUALQ: return truth(equal(x,y));
///// SECTION 6.3 LISTS AND PAIRS
case PAIRQ: return truth(x instanceof Pair);
case LISTQ: return truth(isList(x));
case CXR: for (int i = name.length()-2;
i >= 1; i--)
x = (name.charAt(i) == 'a') ?
first(x) : rest(x);
return x;
case CONS: return cons(x, y);
case CAR: return first(x);
case CDR: return rest(x);
case SETCAR: return setFirst(x, y);
case SETCDR: return setRest(x, y);
case SECOND: return second(x);
case THIRD: return third(x);
case NULLQ: return truth(x == null);
case LIST: return args;
case LENGTH: return num(length(x));
case APPEND: return (args == null) ?
null : append(args);
case REVERSE: return reverse(x);
case LISTTAIL: for (int k = (int)num(y);
k>0; k--) x = rest(x);
return x;
case LISTREF: for (int k = (int)num(y);
k>0; k--) x = rest(x);
return first(x);
case MEMQ: return memberAssoc(x, y, 'm', 'q');
case MEMV: return memberAssoc(x, y, 'm', 'v');
case MEMBER: return memberAssoc(x, y, 'm', ' ');
case ASSQ: return memberAssoc(x, y, 'a', 'q');
case ASSV: return memberAssoc(x, y, 'a', 'v');
case ASSOC: return memberAssoc(x, y, 'a', ' ');
//////////////// SECTION 6.4 SYMBOLS
case SYMBOLQ:
return truth(x instanceof String);
case SYMBOLTOSTRING:
return sym(x).toCharArray();
case STRINGTOSYMBOL:
return new String(str(x)).intern();
//////////////// SECTION 6.5 NUMBERS
case NUMBERQ: return truth(x instanceof Number);
case ODDQ:
return truth(Math.abs(num(x)) % 2 != 0);
case EVENQ:
return truth(Math.abs(num(x)) % 2 == 0);
case ZEROQ: return truth(num(x) == 0);
case POSITIVEQ: return truth(num(x) > 0);
case NEGATIVEQ: return truth(num(x) < 0);
case INTEGERQ: return truth(isExact(x));
case INEXACTQ: return truth(!isExact(x));
case LT: return numCompare(args, '<');
case GT: return numCompare(args, '>');
case EQ: return numCompare(args, '=');
case LE: return numCompare(args, 'L');
case GE: return numCompare(args, 'G');
case MAX: return numCompute(args,
'X', num(x));
case MIN: return numCompute(args,
'N', num(x));
case PLUS: return numCompute(args,
'+', 0.0);
case MINUS: return numCompute(rest(args),
'-', num(x));
case TIMES: return numCompute(args, '*', 1.0);
case DIVIDE: return numCompute(rest(args),
'/', num(x));
case QUOTIENT: double d = num(x)/num(y);
return num(d > 0 ?
Math.floor(d) : Math.ceil(d));
case REMAINDER:
return num((long)num(x) % (long)num(y));
case MODULO:
long xi = (long)num(x),
yi = (long)num(y),
m = xi % yi;
return num((xi*yi > 0 || m == 0) ?
m : m + yi);
case ABS: return num(Math.abs(num(x)));
case FLOOR: return num(Math.floor(num(x)));
case CEILING: return num(Math.ceil(num(x)));
case TRUNCATE: d = num(x);
return num((d < 0.0) ?
Math.ceil(d) : Math.floor(d));
case ROUND: return num(Math.round(num(x)));
case EXP: return num(Math.exp(num(x)));
case LOG: return num(Math.log(num(x)));
case SIN: return num(Math.sin(num(x)));
case COS: return num(Math.cos(num(x)));
case TAN: return num(Math.tan(num(x)));
case ASIN: return num(Math.asin(num(x)));
case ACOS: return num(Math.acos(num(x)));
case ATAN: return num(Math.atan(num(x)));
case SQRT: return num(Math.sqrt(num(x)));
case EXPT:
return num(Math.pow(num(x), num(y)));
case NUMBERTOSTRING:
return numberToString(x, y);
case STRINGTONUMBER:
return stringToNumber(x, y);
case GCD:
return (args == null) ? ZERO : gcd(args);
case LCM:
return (args == null) ? ONE : lcm(args);
//////////////// SECTION 6.6 CHARACTERS
case CHARQ:
return truth(x instanceof Character);
case CHARALPHABETICQ:
return truth(Character.isLetter(chr(x)));
case CHARNUMERICQ:
return truth(Character.isDigit(chr(x)));
case CHARWHITESPACEQ:
return truth(Character.isWhitespace(chr(x)));
case CHARUPPERCASEQ:
return truth(Character.isUpperCase(chr(x)));
case CHARLOWERCASEQ:
return truth(Character.isLowerCase(chr(x)));
case CHARTOINTEGER:
return new Double((double)chr(x));
case INTEGERTOCHAR:
return chr((char)(int)num(x));
case CHARUPCASE:
return chr(Character.toUpperCase(chr(x)));
case CHARDOWNCASE:
return chr(Character.toLowerCase(chr(x)));
case CHARCMP+EQ:
return truth(charCompare(x, y, false) == 0);
case CHARCMP+LT:
return truth(charCompare(x, y, false) < 0);
case CHARCMP+GT:
return truth(charCompare(x, y, false) > 0);
case CHARCMP+GE:
return truth(charCompare(x, y, false) >= 0);
case CHARCMP+LE:
return truth(charCompare(x, y, false) <= 0);
case CHARCICMP+EQ:
return truth(charCompare(x, y, true) == 0);
case CHARCICMP+LT:
return truth(charCompare(x, y, true) < 0);
case CHARCICMP+GT:
return truth(charCompare(x, y, true) > 0);
case CHARCICMP+GE:
return truth(charCompare(x, y, true) >= 0);
case CHARCICMP+LE:
return truth(charCompare(x, y, true) <= 0);
case ERROR: return error(stringify(args));
//////////// SECTION 6.7 STRINGS
case STRINGQ:
return truth(x instanceof char[]);
case MAKESTRING:
char[] str = new char[(int)num(x)];
if (y != null) {
char c = chr(y);
for (int i = str.length-1;
i >= 0; i--) str[i] = c;
}
return str;
case STRING:
return listToString(args);
case STRINGLENGTH:
return num(str(x).length);
case STRINGREF:
return chr(str(x)[(int)num(y)]);
case STRINGSET:
Object z = third(args);
str(x)[(int)num(y)] = chr(z); return z;
case SUBSTRING:
int start = (int)num(y),
end = (int)num(third(args));
return new String(str(x),
start,
end-start).toCharArray();
case STRINGAPPEND:
return stringAppend(args);
case STRINGTOLIST:
Pair result = null;
char[] str2 = str(x);
for (int i = str2.length-1; i >= 0; i--)
result = cons(chr(str2[i]), result);
return result;
case LISTTOSTRING: return listToString(x);
case STRINGCMP+EQ:
return truth(stringCompare(x,y,false) == 0);
case STRINGCMP+LT:
return truth(stringCompare(x,y,false) < 0);
case STRINGCMP+GT:
return truth(stringCompare(x,y,false) > 0);
case STRINGCMP+GE:
return truth(stringCompare(x,y,false) >= 0);
case STRINGCMP+LE:
return truth(stringCompare(x,y,false) <= 0);
case STRINGCICMP+EQ:
return truth(stringCompare(x,y,true) == 0);
case STRINGCICMP+LT:
return truth(stringCompare(x,y,true) < 0);
case STRINGCICMP+GT:
return truth(stringCompare(x,y,true) > 0);
case STRINGCICMP+GE:
return truth(stringCompare(x,y,true) >= 0);
case STRINGCICMP+LE:
return truth(stringCompare(x,y,true) <= 0);
/////////// SECTION 6.8 VECTORS
case VECTORQ:
return truth(x instanceof Object[]);
case MAKEVECTOR:
Object[] vec = new Object[(int)num(x)];
if (y != null) {
for (int i = 0;
i < vec.length; i++) vec[i] = y;
}
return vec;
case VECTOR:
return listToVector(args);
case VECTORLENGTH:
return num(vec(x).length);
case VECTORREF:
return vec(x)[(int)num(y)];
case VECTORSET:
return vec(x)[(int)num(y)] = third(args);
case VECTORTOLIST:
return vectorToList(x);
case LISTTOVECTOR:
return listToVector(x);
///////// SECTION 6.9 CONTROL FEATURES
case EVAL:
return interp.eval(x);
case FORCE:
return (!(x instanceof Procedure)) ? x
: proc(x).apply(interp, null);
case MACROEXPAND:
return Macro.macroExpand(interp, x);
case PROCEDUREQ:
return truth(x instanceof Procedure);
case APPLY:
return proc(x).apply(interp,
listStar(rest(args)));
case MAP:
return map(proc(x), rest(args), interp, list(null));
case FOREACH:
return map(proc(x), rest(args), interp, null);
case CALLCC:
RuntimeException cc = new RuntimeException();
Continuation proc = new Continuation(cc);
try { return proc(x).apply(interp, list(proc)); }
catch (RuntimeException e) {
if (e == cc) return proc.value; else throw e;
}
/////////// SECTION 6.10 INPUT AND OUPUT
case EOFOBJECTQ:
return truth(x == InputPort.EOF);
case INPUTPORTQ:
return truth(x instanceof InputPort);
case CURRENTINPUTPORT:
return interp.input;
case OPENINPUTFILE:
return openInputFile(x);
case CLOSEINPUTPORT:
return inPort(x, interp).close();
case OUTPUTPORTQ:
return truth(x instanceof PrintWriter);
case CURRENTOUTPUTPORT:
return interp.output;
case OPENOUTPUTFILE:
return openOutputFile(x);
case CALLWITHOUTPUTFILE:
PrintWriter p = null;
try { p = openOutputFile(x);
z = proc(y).apply(interp, list(p));
} finally { if (p != null) p.close(); }
return z;
case CALLWITHINPUTFILE:
InputPort p2 = null;
try { p2 = openInputFile(x);
z = proc(y).apply(interp, list(p2));
} finally { if (p2 != null) p2.close(); }
return z;
case CLOSEOUTPUTPORT:
outPort(x, interp).close(); return TRUE;
case READCHAR:
return inPort(x, interp).readChar();
case PEEKCHAR:
return inPort(x, interp).peekChar();
case LOAD:
return interp.load(x);
case READ:
return inPort(x, interp).read();
case EOF_OBJECT:
return truth(InputPort.isEOF(x));
case WRITE:
return write(x, outPort(y, interp), true);
case DISPLAY:
return write(x, outPort(y, interp), false);
case NEWLINE:
outPort(x, interp).println();
outPort(x, interp).flush(); return TRUE;
//////////////// EXTENSIONS
case CLASS:
try {
return Class.forName(stringify(x, false));
}
catch (ClassNotFoundException e) {
return FALSE;
}
case NEW:
try {
return JavaMethod.toClass(x).newInstance();
}
catch (ClassCastException e) { ; }
catch (NoSuchMethodError e) { ; }
catch (InstantiationException e) { ; }
catch (ClassNotFoundException e) { ; }
catch (IllegalAccessException e) { ; }
return FALSE;
case METHOD:
return new JavaMethod(stringify(x, false),
y,
rest(rest(args)));
case EXIT:
System.exit((x == null) ? 0 : (int)num(x));
case LISTSTAR:
return listStar(args);
case TIMECALL:
Runtime runtime = Runtime.getRuntime();
runtime.gc();
long startTime = System.currentTimeMillis();
long startMem = runtime.freeMemory();
Object ans = FALSE;
int nTimes = (y == null ? 1 : (int)num(y));
for (int i = 0; i < nTimes; i++) {
ans = proc(x).apply(interp, null);
}
long time =
System.currentTimeMillis() - startTime;
long mem = startMem - runtime.freeMemory();
return cons(ans,
list(list(num(time), "msec"),
list(num(mem), "bytes")));
default:
return
error("internal error: unknown primitive: "
+ this + " applied to " + args);
}
}
public static char[] stringAppend(Object args) {
StringBuffer result = new StringBuffer();
for(; args instanceof Pair; args = rest(args)) {
result.append(stringify(first(args), false));
}
return result.toString().toCharArray();
}
public static Object
memberAssoc(Object obj,
Object list, char m, char eq) {
while (list instanceof Pair) {
Object target = (m == 'm') ?
first(list) : first(first(list));
boolean found;
switch (eq) {
case 'q': found = (target == obj); break;
case 'v': found = eqv(target, obj); break;
case ' ': found = equal(target, obj); break;
default:
warn("Bad option to memberAssoc:"
+ eq); return FALSE;
}
if (found)
return (m == 'm') ?
list : first(list);
list = rest(list);
}
return FALSE;
}
public static Object
numCompare(Object args, char op) {
while (rest(args) instanceof Pair) {
double x = num(first(args)); args = rest(args);
double y = num(first(args));
switch (op) {
case '>': if (!(x > y))
return FALSE; break;
case '<': if (!(x < y))
return FALSE; break;
case '=': if (!(x == y))
return FALSE; break;
case 'L': if (!(x <= y))
return FALSE; break;
case 'G': if (!(x >= y))
return FALSE; break;
default:
error("internal error: unrecognized op: "
+ op); break;
}
}
return TRUE;
}
public static Object
numCompute(Object args,
char op, double result) {
if (args == null) {
switch (op) {
case '-': return num(0 - result);
case '/': return num(1 / result);
default: return num(result);
}
} else {
while (args instanceof Pair) {
double x = num(first(args));
args = rest(args);
switch (op) {
case 'X': if (x > result)
result = x; break;
case 'N': if (x < result)
result = x; break;
case '+': result += x; break;
case '-': result -= x; break;
case '*': result *= x; break;
case '/': result /= x; break;
default:
error("internal error: unrecognized op: "
+ op); break;
}
}
return num(result);
}
}
/** Return the sign of the argument:
+1, -1, or 0. **/
static int sign(int x) {
return (x > 0) ? +1 : (x < 0) ? -1 : 0;
}
/** Return <0 if x is alphabetically first,
* >0 if y is first,
* 0 if same. Case insensitive iff ci is true.
* Error if not both chars. **/
public static int
charCompare(Object x,
Object y, boolean ci) {
char xc = chr(x), yc = chr(y);
if (ci) { xc = Character.toLowerCase(xc);
yc = Character.toLowerCase(yc); }
return xc - yc;
}
/** Return <0 if x is alphabetically first,
* >0 if y is first,
* 0 if same. Case insensitive iff ci is true.
* Error if not strings. **/
public static int
stringCompare(Object x,
Object y, boolean ci) {
if (x instanceof char[] &&
y instanceof char[]) {
char[] xc = (char[])x, yc = (char[])y;
for (int i = 0; i < xc.length; i++) {
int diff = (!ci) ? xc[i] - yc[i]
: Character.toUpperCase(xc[i])
- Character.toUpperCase(yc[i]);
if (diff != 0) return diff;
}
return xc.length - yc.length;
} else {
error("expected two strings, got: "
+ stringify(list(x, y)));
return 0;
}
}
static Object
numberToString(Object x, Object y) {
int base = (y instanceof Number) ?
(int)num(y) : 10;
if (base != 10 ||
num(x) == Math.round(num(x))) {
// An integer
return Long.toString((long)num(x),
base).toCharArray();
} else {
// A floating point number
return x.toString().toCharArray();
}
}
static Object stringToNumber(Object x, Object y) {
int base =
(y instanceof Number) ? (int)num(y) : 10;
try {
return (base == 10)
? Double.valueOf(stringify(x, false))
: num(Long.parseLong(stringify(x, false),
base));
}
catch (NumberFormatException e) {
return FALSE;
}
}
static Object gcd(Object args) {
long gcd = 0;
while (args instanceof Pair) {
gcd = gcd2(Math.abs((long)num(first(args))),
gcd);
args = rest(args);
}
return num(gcd);
}
static long gcd2(long a, long b) {
if (b == 0) return a;
else return gcd2(b, a % b);
}
static Object lcm(Object args) {
long L = 1, g = 1;
while (args instanceof Pair) {
long n = Math.abs((long)num(first(args)));
g = gcd2(n, L);
L = (g == 0) ? g : (n / g) * L;
args = rest(args);
}
return num(L);
}
static boolean isExact(Object x) {
if (!(x instanceof Double)) return false;
double d = num(x);
return (d == Math.round(d) &&
Math.abs(d) < 102962884861573423.0);
}
static PrintWriter
openOutputFile(Object filename) {
try {
return new
PrintWriter(new
FileWriter(stringify(filename, false)));
}
catch (FileNotFoundException e) {
return (PrintWriter)
error("No such file: " + stringify(filename));
}
catch (IOException e) {
return (PrintWriter)error("IOException: " + e);
}
}
static InputPort openInputFile(Object filename) {
try {
return new
InputPort(new
FileInputStream(stringify(filename,
false)));
} catch (FileNotFoundException e) {
return (InputPort)error("No such file: "
+ stringify(filename));
} catch (IOException e) {
return (InputPort)error("IOException: " + e);
}
}
static boolean isList(Object x) {
Object slow = x, fast = x;
for(;;) {
if (fast == null) return true;
if (slow == rest(fast) ||
!(fast instanceof Pair)
|| !(slow instanceof Pair)) return false;
slow = rest(slow);
fast = rest(fast);
if (fast == null) return true;
if (!(fast instanceof Pair)) return false;
fast = rest(fast);
}
}
static Object append(Object args) {
if (rest(args) == null) return first(args);
else return append2(first(args),
append(rest(args)));
}
static Object append2(Object x, Object y) {
if (x instanceof Pair)
return cons(first(x), append2(rest(x), y));
else return y;
}
/** Map proc over a list of lists of args,
* in the given interpreter.
* If result is non-null,
* accumulate the results of each call there
* and return that at the end.
* Otherwise, just return null. **/
static Pair map(Procedure proc,
Object args,
Scheme interp,
Pair result) {
Pair accum = result;
if (rest(args) == null) {
args = first(args);
while (args instanceof Pair) {
Object x = proc.apply(interp,
list(first(args)));
if (accum != null)
accum = (Pair) (accum.rest = list(x));
args = rest(args);
}
} else {
Procedure car = proc(interp.eval("car")),
cdr = proc(interp.eval("cdr"));
while (first(args) instanceof Pair) {
Object x = proc.apply(interp,
map(car,
list(args),
interp,
list(null)));
if (accum != null)
accum = (Pair) (accum.rest = list(x));
args = map(cdr,
list(args),
interp, list(null));
}
}
return (Pair)rest(result);
}
}
generated through LaTeX2HTML. M.Inaba 平成18年5月6日