📄 lispobject.java
字号:
/*
* MC2 -- j2me spreadsheet
*
* Copyright (c) 2004-2006 Michael Zemljanukha (mixaz@mail.ru)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.wapindustrial.calc;
import java.util.*;
import java.io.*;
/**
*
* @author mzemlyan
*/
public class LispObject {
/** This function was added because Nokia 6600 had a bug in Character.isDigit()
* and returned TRUE for isDigit(':')
*/
//#ifdef ISDIGIT
//# public static final boolean isDigit( char cc) {
//# return cc >= '0' && cc <= '9';
//# }
//#endif
/** max .mc2 file size when loading, kBytes */
private static final int MAX_MC2FILE_SIZE = 15;
// public LispObject() {} // for zero atoms
public static final LispObject NIL = new LispObject();
/** Evaluates s-exp - this is a basic interface for Lisp objects
* When evluating atoms return themselves, functors do some
* calculations and return evaluated objects, often atoms.
* Inherited classes are supposed to implement this method.
* The default behaviour (implemented in LispObject) is to return the
* object itself, so atoms are allowed to not implement it.
* For current MC2 implementation only NameObject
* and FunctorList has got it's own implementation of evaluateSExp()
* @throws EvaluateException If cannot evaluate for some reason
* @return evaluated LispObject
*/
public LispObject evaluateSExp() throws EvaluateException {
// this for atoms & list, calculate functions for functors
return this;
}
// /** Evaluates and resolves references if it's a Referrence
// * @throws EvaluateException
// * @return Atom and not a Reference
// */
// public LispObject evaluateSExpRef() throws EvaluateException {
// return evaluateSExp().getReferredValue();
// }
/** The same as evaluateSExp() but evaluates a QuotedList as well.
* Used when code is stored in quoted list
* @throws EvaluateException
* @return for QuotedList it's result of evaluation of the last item in the list
* @see evaluateSExp
*/
public LispObject interpret() throws EvaluateException {
return evaluateSExp();
}
/** Shifts references in this sexp.
* The difference with shiftReferences() - shiftReferences changes references according given range,
* which may be outside the cell. moveReferences moves the current cell.
* @param di di to destination (rows)
* @param dj dj to destination (columns
* @return new object if something was shifted (any relative reference encountered)
* @see shiftReferences
*/
public LispObject moveReferences( int di, int dj ) {
return this; // for immutable items
}
public LispObject shiftReferences(int I1, int J1, int dI, int dJ) {
return this;
}
// /** To be overrided in Referrence calls. Returns referred value by a range, value of
// * top-left cell in the range. Evaluates
// * @returns Referrenced value, if it's a Reference too, recursivelly calculates it as well
// */
// public LispObject getReferredValue() {
// return this;
// }
/* =================================
* Interfaces for type converting
* Used in formula processing
* Order makes sence as datatypes are converted to higher one in WS formula expressions
*/
static final int TYPE_UNKNOWN = 0;
/** represents empty cell as well (not sure if it was right decision) */
static final int TYPE_NIL = 1;
static final int TYPE_REFERENCE = 2;
static final int TYPE_NAME = 3;
static final int TYPE_FUNCTORLIST = 4;
static final int TYPE_QUOTEDLIST = 5;
static final int TYPE_BOOLEAN = 6;
static final int TYPE_SHORT = 7;
static final int TYPE_LONG = 8;
static final int TYPE_FLOAT = 9;
static final int TYPE_STRING = 10;
static final int TYPE_ERROR = 11;
static final int TYPE_DATE = 12;
static final int TYPE_ROWCOLUMN = 13;
static final int TYPE_CELL = 14;
static final int TYPE_SHEET = 15;
static final int TYPE_FUNCTION = 16;
static final int TYPE_PROFILE = 17; // user profile object, to be used on server side only
public int typeNumber() {
return TYPE_NIL;
}
/* ==============================================================
* Portability functions (to fix platform bugs)
*/
public static final byte[] getBytesUTF8(String ss) {
if(ss==null)
throw new IllegalArgumentException();
byte value[] = {};
//#ifndef UTF8
//# value = ss.getBytes();
//#else
try {
value = ss.getBytes("UTF-8");
}
catch (UnsupportedEncodingException e) {
debug("can't encode name to UTF-8: <"+ss+">");
}
//#endif
return value;
}
public static final String getStringUTF8( byte buf[], int offset, int len) {
if(buf==null)
throw new IllegalArgumentException();
//#ifndef UTF8
//# return new String(buf,offset,len);
//#else
try {
return new String(buf,offset,len,"UTF-8");
}
catch (UnsupportedEncodingException e) {
debug("cannot decode name from UTF-8");
throw new IllegalStateException();
}
//#endif
}
public static final Hashtable createHashtable(int capacity) {
//#ifdef HASHTABLE_ZERO
//# if (capacity==0)
//# return new Hashtable();
//#endif
return new Hashtable(capacity);
}
/** converts object to given type
* @param type
* @throws EvaluateException
* @return
*/
public LispObject convertToType( int type ) throws EvaluateException {
if( this == NIL ) {
LispObject rez = this;
switch( type ) {
case TYPE_SHORT:
rez = ShortAtom.ZERO;
break;
case TYPE_LONG:
rez = LongAtom.ZERO;
break;
case TYPE_FLOAT:
rez = FloatAtom.ZERO;
break;
// default: // to STRING
// return super.convertToType( type );
}
return rez;
}
if( type == TYPE_STRING )
return new StringAtom( toString() );
throw new EvaluateException( "cannot convert type "+typeNumber()+" to "+type, this );
}
/* ===================================== */
/**
* To represent complex atom as list.
* It calls getPart() up to listSize() times and uses FunctorListN form.
* Subclasses may want to implement it to use smaller FunctorList,
* or for efficiency.
* @return representation of complex atom as a functor list
*/
FunctorList toList() {
int len = listSize();
if( len == 0 ) {
// atoms cannot be represented as lists
return null;
}
LispObject args[] = new LispObject[len-1];
for( int i=1; i<len; i++) {
args[i-1] = getPart(i);
}
try {
return new FunctorListN((NameObjectBase)getPart(0),args);
}
catch(ClassCastException e) {
throw new IllegalArgumentException("wrong getPart(0) implementation");
}
}
/**
* Returns member of a complicated atom (represented as a list)
* @param item member number (in list representation).
* When item = 0 returns functor name
* @return part of list
* @throws IllegalArgumentException for illegal item number
*/
LispObject getPart(int item) throws IllegalArgumentException {
// atoms cannot be represented as lists
// this function is also called by implementations if part number is wrong
throw new IllegalArgumentException("Wrong call of getPart()");
}
/**
* Sets item of list to new value
* @param item item number
* @param newvalue new value to set to
* @return old value of the list item
* @throws IllegalArgumentException if item number is illegal or if newvalue is wrong type,
* or item is readonly and can't be set
*/
LispObject setPart(int item, LispObject newvalue) throws IllegalArgumentException {
throw new IllegalArgumentException("Wrong call of setPart()");
}
/**
* Used in Lisp representation
* @param sb
*/
public void toBuffer(StringBuffer sb) {
FunctorList list = toList();
if (list != null) {
list.toBuffer(sb);
return;
}
if (this == NIL)
sb.append("nil");
else {
sb.append('<');
sb.append(getClass().getName());
sb.append('>');
}
}
/**
* Used to represent atoms (and lists) in worksheets formulas. The representation must be
* supported by Operator.parseFormula(), this is related interfaces. To be overrided by
* implementations.
*
* @param sb
* Buffer to write to. To get a string use toFormulaString()
*/
public void toFormulaBuffer( StringBuffer sb ) { // to be displayed in FW
// adds nothing for NIL implementation
if( this == NIL )
return;
// if not overriden, lisp representation will be used
toBuffer( sb );
}
/**
* Used to represent atoms as values in cells. Not actual for functors
* @param sb
* buffer to append to
* @param format
* cell format
*/
public void toValueBuffer( StringBuffer sb, int format ) {
// intended for atoms
// adds noyhing for NIL implementation
if( this == NIL )
return; // empty
toBuffer( sb );
}
/** Gets string representation of a lisp object to be used in WS formulas.
* This string must be parsed by Operator.parseFormula().
* Just call toFormulaBuffer().
* @return String representation of atom/list in WS formulas
*/
public String toFormulaString() {
StringBuffer sb = new StringBuffer();
toFormulaBuffer( sb );
return sb.toString();
}
// intended for atoms
public String toValueString( int format ) {
StringBuffer sb = new StringBuffer();
toValueBuffer( sb, format );
return sb.toString();
}
public String toString() {
StringBuffer sb = new StringBuffer();
toBuffer( sb );
return sb.toString();
}
protected void addIdent( StringBuffer sb, int ident ) {
for( int i=0; i<ident; i++ )
sb.append(" ");
}
//#ifdef JAVA_COMPILER
public void toJavaBuffer( StringBuffer sb, int ident, FunctorList parent ) {
FunctorList list = toList();
if( list != null ) {
list.toJavaBuffer( sb, ident, null );
return;
}
addIdent( sb, ident );
sb.append( "NIL" );
}
/** used to print lisp objects as java code, to compile lisp -> native (JVM)
* @return Java code constructing corresponding lisp code
* by calling constructors (new LispObject())
* Use LispObject.evaluateSExp() to run this code
*/
public String toJavaString() {
StringBuffer sb = new StringBuffer();
toJavaBuffer( sb, 0, null );
return sb.toString();
}
//#endif
//#ifndef MINIMAL_SET
/**
* Preprocesses lisp tree, evaluates preprocessor functors such as ($if)
* [shouldn't it be done for (ref) or (qlist)?]
* @param functor functor to be evaluated
* @return tree with replaced preprocessor functors
* @throws EvaluateException when can't evaluate sexp of conditional
*/
public LispObject preprocess(NameObjectBase functor) throws EvaluateException {
return this;
}
//#endif
// to display on sheet screen, actual for references ie.
// actual for atoms since all other cannot be result of expression
// will be extended to support formatters
// public String toScreenString() {
// return toString();
// }
// =========================================================
// FunctorList factory
// =========================================================
public static final QuotedList EMPTY_LIST = new QuotedList(new LispObject[0]);
// throws classcastexception if functor is not a nameobject
public static FunctorList createFunctorList(LispObject args[]) throws ClassCastException {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -