package builtin.system; import builtin.BuiltinSub; import java.math.BigInteger; import gui.Constants; import gui.Heap; import gui.MintException; import gui.Pointer; import gui.PointerTools; import gui.Rational; import gui.SmartList; import gui.Subprogram; /** * * @author Oliver Chu */ public class SizeInBytes extends BuiltinSub { private static final Pointer ONE_BIT = Heap.allocRat(Rational.makeRat(1, 8)); private static final Pointer NYBBLE = Heap.allocRat(Rational.makeRat(1, 2)); @Override public Pointer apply(SmartList<Pointer> args) throws MintException { Pointer p = new Pointer((byte) 0, 0); try { if (args == null || args.size() == 0) { return Constants.ZERO; } p = args.get(0); switch (p.type) { case Constants.NULL_TYPE: return Constants.ZERO; case Constants.INT_TYPE: return Heap.allocateInt(4); case Constants.REAL_TYPE: return Heap.allocateInt(8); case Constants.TRUTH_TYPE: return ONE_BIT; case Constants.BIG_INT_TYPE: case Constants.PRECISE_REAL_TYPE: // Big integers and precise reals store // their digits as 4-bit values. String asStr = PointerTools.dereferenceAsString(p); float fl = asStr.length(); fl *= 0.5; if (fl < 1.0) { return NYBBLE; } else { return Heap.allocateReal(fl); } case Constants.RAT_TYPE: return Heap.allocateInt(16); case Constants.STR_TYPE: { String s = PointerTools.dereferenceString(p); return Heap.allocateInt(s.length() + 1); } case Constants.BYTES_TYPE: { SmartList<Byte> b = PointerTools.dereferenceBytes(p); return Heap.allocateInt(b.size() + 1); } case Constants.LIST_TYPE: case Constants.TABLE_TYPE: { SmartList<Pointer> pList = PointerTools.dereferenceList(p); if (pList.isEmpty()) { return Constants.ZERO; } Double sum = 0.0; // Recursively find the number of bytes in // this list and all sublists. for (Pointer p2 : pList) { SmartList<Pointer> arguments = new SmartList<Pointer>(); arguments.add(p2); sum += PointerTools.dereferenceReal( new SizeInBytes().apply(arguments)); } return Heap.allocateReal(sum); } case Constants.SUBPROGRAM_TYPE: { Subprogram sb = PointerTools.dereferenceSub(p); SmartList<SmartList<Pointer>> body = sb.originalBody; for (SmartList<Pointer> lineOfCode : body) { Pointer line = Heap.allocateList(lineOfCode); SmartList<Pointer> listOfOne = new SmartList<Pointer>(); listOfOne.add(line); Double dbl = PointerTools.dereferenceReal( new SizeInBytes().apply(listOfOne)); Long ell = dbl.longValue(); return Heap.allocateBigInt(new BigInteger( ell.toString())); } } } } catch (Throwable t) {} return Heap.allocateInt(PointerTools.dereferenceAsString(p).length()); } }