PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/jasi/semantics/procedure/CompoundProcedure.java

http://jasi-himanshu.googlecode.com/
Java | 112 lines | 83 code | 15 blank | 14 comment | 26 complexity | 700a157cfb29ad28ec31c624f51b987d MD5 | raw file
  1. package jasi.semantics.procedure;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import jasi.Constants;
  5. import jasi.datatype.SEmptyList;
  6. import jasi.datatype.SPair;
  7. import jasi.datatype.SVariable;
  8. import jasi.semantics.Environment;
  9. import jasi.semantics.Scheme;
  10. import jasi.semantics.Utils;
  11. public class CompoundProcedure extends Procedure {
  12. //environment at the time of creation of this compound
  13. //procedure
  14. //we keep a handle to it to provide lexically scoped
  15. //free variables
  16. private Environment creationEnv;
  17. //argument list
  18. private List<SVariable> argVars; //fixed variables
  19. //list of all args appearing after fixed args
  20. //kept null if procedure has fixed length arguments
  21. private SVariable restArgs;
  22. //body
  23. private SPair body; //this will be a valid begin expression.
  24. public CompoundProcedure(Object paramArgs, Object bodyArg,
  25. Environment env) {
  26. ArrayList<SVariable> params = null;
  27. Object tmp = paramArgs;
  28. if(paramArgs instanceof SVariable) {
  29. restArgs = (SVariable)paramArgs;
  30. this.argVars = new ArrayList<SVariable>();
  31. }
  32. else {
  33. while(!(tmp instanceof SEmptyList)) {
  34. Object o = Utils.first(tmp);
  35. Utils.validateType(o, SVariable.class);
  36. if(params == null) params = new ArrayList<SVariable>();
  37. params.add((SVariable)o);
  38. tmp = Utils.cdr(tmp);
  39. if(tmp instanceof SVariable) {
  40. restArgs = (SVariable)tmp;
  41. break;
  42. }
  43. }
  44. this.argVars = params;
  45. }
  46. this.body = new SPair(SVariable.getInstance(Constants.KEYWORD_BEGIN), bodyArg);
  47. this.creationEnv = env;
  48. }
  49. //NOTE: this implementation doesn't have tail recursion optimization
  50. public Object apply(Object o, Environment env) {
  51. //the environment coming in the input is ignored, rather the one
  52. //at the time of creation of this procedure is used for all purposes
  53. //this is to provide lexically scoped free variables or else the impl
  54. //will become that of dynamically scoped free variables.
  55. ArrayList<Object> args = null;
  56. if(o != null) {
  57. if(o instanceof ArrayList)
  58. args = (ArrayList)o;
  59. else
  60. throw new RuntimeException("arguments not ArrayList:" + o);
  61. }
  62. //check length of provided arguments
  63. int lenInputArgs = (args == null)? 0 : args.size();
  64. int lenArgVars = (argVars == null)? 0 : argVars.size();
  65. if(restArgs == null) {
  66. if(lenArgVars != lenInputArgs)
  67. throw new RuntimeException("expecing " + lenArgVars + " arguments, but" +
  68. " received " + lenInputArgs + ".");
  69. }
  70. else {
  71. if(lenArgVars > lenInputArgs)
  72. throw new RuntimeException("expecing atleast " + lenArgVars + " arguments, but" +
  73. " received " + lenInputArgs + " only.");
  74. }
  75. if(lenInputArgs == 0) {
  76. env = creationEnv.extendEnvironment();
  77. if(restArgs != null)
  78. env.putBinding(restArgs, SEmptyList.getInstance());
  79. }
  80. else if(restArgs == null){
  81. env = creationEnv.extendEnvironment(argVars, args);
  82. }
  83. else {
  84. Object inputRestArgs = SEmptyList.getInstance();
  85. if(lenInputArgs > lenArgVars) {
  86. for(int i= args.size()-1; args.size() > lenArgVars; i--)
  87. inputRestArgs = Utils.cons(args.remove(i), inputRestArgs);
  88. }
  89. env = creationEnv.extendEnvironment(argVars, args);
  90. env.putBinding(restArgs, inputRestArgs);
  91. }
  92. return Scheme.eval(body, env);
  93. }
  94. public String toString() {
  95. return "#<Compound-Procedure>#";
  96. }
  97. }