package gui; import builtin.BuiltinSub; /** * * @author Oliver Chu */ public class Subprogram { private String name; private SmartList<Pointer> argNames; private SmartList<SmartList<Pointer>> body; public SmartList<SmartList<Pointer>> originalBody; private BuiltinSub sub; private MintObject virtualArgs; private int thisPointer; private String thisPointerName; private void copyToOriginalBody() { originalBody = new SmartList<SmartList<Pointer>>(); for (SmartList<Pointer> eachList : body) { SmartList<Pointer> newList = new SmartList<Pointer>(); for (Pointer p : eachList) { newList.add(p); } originalBody.add(newList); } } public Subprogram(String name, SmartList<Pointer> argNames, BuiltinSub sub) { this.name = name; this.argNames = argNames; this.body = new SmartList<SmartList<Pointer>>(); this.sub = sub; this.virtualArgs = null; thisPointer = -1; thisPointerName = ""; copyToOriginalBody(); } public Subprogram(String name, SmartList<Pointer> argNames, SmartList<SmartList<Pointer>> body) { this.name = name; this.argNames = argNames; this.body = body; this.sub = null; this.virtualArgs = null; thisPointer = -1; thisPointerName = ""; copyToOriginalBody(); } public Subprogram(String name, SmartList<Pointer> argNames, SmartList<SmartList<Pointer>> body, MintObject virtualArgs) { this.name = name; this.argNames = argNames; this.body = body; this.sub = null; this.virtualArgs = virtualArgs; thisPointer = -1; thisPointerName = ""; copyToOriginalBody(); } public void setThisPointer(int value) { thisPointer = value; } public void setThisPointerName(String value) { thisPointerName = value; } public void setVirtualArgs(MintObject o) { virtualArgs = o; } public String getName() { return name; } public int getArgNamesLength() { return argNames.size(); } public SmartList<Pointer> getArgNames() { return argNames; } public void addToBody(SmartList<Pointer> line) { body.add(line); copyToOriginalBody(); } public SmartList<SmartList<Pointer>> getBody() { return body; } public void setBody(SmartList<SmartList<Pointer>> bod) { body = bod; } public Pointer execute(Environment env, SmartList<String> imports, SmartList<Pointer> argValues, Interpreter interpreter) throws MintException { MintObject newFrame = new MintObject(); if (argValues.isEmpty() && argNames.size() == 2) { Integer keyword = PointerTools.dereferenceKeyword(argNames.get(1)); if (keyword != null && keyword == Constants.DOUBLE_DOT) { SmartList<Pointer> list = new SmartList<Pointer>(); String n = PointerTools.dereferenceName(argNames.get(0)); newFrame.put(n, Heap.allocateList(list)); } } int i = 0; if (argValues.size() > argNames.size() && !ListTools.containsPointer(argNames, new Pointer(Constants.KEYWORD_TYPE, Constants.DOUBLE_DOT))) { throw new MintException("Subprogram " + name + " takes " + argNames.size() + " arguments (" + argValues.size() + " given)"); } for (Pointer value : argValues) { try { String n = PointerTools.dereferenceName(argNames.get(i)); if (i + 1 < argNames.size()) { Integer keyword = PointerTools.dereferenceKeyword(argNames.get(i + 1)); if (keyword != null && keyword == Constants.DOUBLE_DOT) { // Store variable args: Pointer list = Heap.allocateList(argValues.subList(i)); newFrame.put(n, list); if (PointerTools.dereferenceList(list).get(0).type == Constants.NULL_TYPE) { newFrame.put(n, Heap.allocateList(new SmartList<Pointer>())); } break; } i++; } newFrame.put(n, value); } catch (IndexOutOfBoundsException ex) { throw new MintException("Subprogram " + name + " takes " + argNames.size() + " arguments (" + argValues.size() + " given)"); } } if (virtualArgs != null) { newFrame.putAll(virtualArgs); } env.addFrame(newFrame); if (thisPointer != -1) { interpreter.setThisPointer(thisPointer); interpreter.setThisPointerName(thisPointerName); } else { interpreter.setThisPointer(-1); interpreter.setThisPointerName(""); } if (sub != null) { env.pop(); argValues.add(Heap.allocateInterpreter(interpreter)); return sub.apply(argValues); } Pointer result = interpreter.execute(body, imports, env); body = originalBody; copyToOriginalBody(); return result; } }