MysoreScript
interpreter.cc
Go to the documentation of this file.
1 #include <string.h>
2 #include "parser.hh"
3 
4 using namespace AST;
5 using namespace MysoreScript;
6 
9 
10 namespace {
16 inline bool needsGC(Obj o)
17 {
18  return (o != nullptr) && ((reinterpret_cast<intptr_t>(o) & 7) == 0);
19 }
20 
22 
29 {
30  return C->AST->interpretClosure(*currentContext, C, nullptr);
31 }
37 {
38  Obj args[] = { o0 };
39  return C->AST->interpretClosure(*currentContext, C, args);
40 }
46 {
47  Obj args[] = { o0, o1 };
48  return C->AST->interpretClosure(*currentContext, C, args);
49 }
55 {
56  Obj args[] = { o0, o1, o2 };
57  return C->AST->interpretClosure(*currentContext, C, args);
58 }
64 {
65  Obj args[] = { o0, o1, o2, o3 };
66  return C->AST->interpretClosure(*currentContext, C, args);
67 }
72 Obj closureTrampoline5(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4)
73 {
74  Obj args[] = { o0, o1, o2, o3, o4 };
75  return C->AST->interpretClosure(*currentContext, C, args);
76 }
81 Obj closureTrampoline6(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4,
82  Obj o5)
83 {
84  Obj args[] = { o0, o1, o2, o3, o4, o5 };
85  return C->AST->interpretClosure(*currentContext, C, args);
86 }
91 Obj closureTrampoline7(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4,
92  Obj o5, Obj o6)
93 {
94  Obj args[] = { o0, o1, o2, o3, o4, o5, o6 };
95  return C->AST->interpretClosure(*currentContext, C, args);
96 }
101 Obj closureTrampoline8(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4,
102  Obj o5, Obj o6, Obj o7)
103 {
104  Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7 };
105  return C->AST->interpretClosure(*currentContext, C, args);
106 }
111 Obj closureTrampoline9(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4,
112  Obj o5, Obj o6, Obj o7, Obj o8)
113 {
114  Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8 };
115  return C->AST->interpretClosure(*currentContext, C, args);
116 }
121 Obj closureTrampoline10(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4,
122  Obj o5, Obj o6, Obj o7, Obj o8, Obj o9)
123 {
124  Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8, o9 };
125  return C->AST->interpretClosure(*currentContext, C, args);
126 }
127 
133 {
134  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
135  Method *mth = methodForSelector(cls, cmd);
136  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, nullptr);
137 }
143 {
144  Obj args[] = { o0 };
145  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
146  Method *mth = methodForSelector(cls, cmd);
147  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
148 }
154 {
155  Obj args[] = { o0, o1 };
156  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
157  Method *mth = methodForSelector(cls, cmd);
158  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
159 }
164 Obj methodTrampoline3(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2)
165 {
166  Obj args[] = { o0, o1, o2 };
167  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
168  Method *mth = methodForSelector(cls, cmd);
169  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
170 }
175 Obj methodTrampoline4(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3)
176 {
177  Obj args[] = { o0, o1, o2, o3 };
178  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
179  Method *mth = methodForSelector(cls, cmd);
180  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
181 }
186 Obj methodTrampoline5(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3,
187  Obj o4)
188 {
189  Obj args[] = { o0, o1, o2, o3, o4 };
190  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
191  Method *mth = methodForSelector(cls, cmd);
192  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
193 }
198 Obj methodTrampoline6(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3,
199  Obj o4, Obj o5)
200 {
201  Obj args[] = { o0, o1, o2, o3, o4, o5 };
202  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
203  Method *mth = methodForSelector(cls, cmd);
204  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
205 }
210 Obj methodTrampoline7(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3,
211  Obj o4, Obj o5, Obj o6)
212 {
213  Obj args[] = { o0, o1, o2, o3, o4, o5, o6 };
214  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
215  Method *mth = methodForSelector(cls, cmd);
216  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
217 }
222 Obj methodTrampoline8(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4,
223  Obj o5, Obj o6, Obj o7)
224 {
225  Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7 };
226  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
227  Method *mth = methodForSelector(cls, cmd);
228  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
229 }
234 Obj methodTrampoline9(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3,
235  Obj o4, Obj o5, Obj o6, Obj o7, Obj o8)
236 {
237  Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8 };
238  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
239  Method *mth = methodForSelector(cls, cmd);
240  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
241 }
246 Obj methodTrampoline10(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3,
247  Obj o4, Obj o5, Obj o6, Obj o7, Obj o8, Obj o9)
248 {
249  Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8, o9 };
250  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
251  Method *mth = methodForSelector(cls, cmd);
252  return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args);
253 }
258  reinterpret_cast<CompiledMethod>(methodTrampoline0),
259  reinterpret_cast<CompiledMethod>(methodTrampoline1),
260  reinterpret_cast<CompiledMethod>(methodTrampoline2),
261  reinterpret_cast<CompiledMethod>(methodTrampoline3),
262  reinterpret_cast<CompiledMethod>(methodTrampoline4),
263  reinterpret_cast<CompiledMethod>(methodTrampoline5),
264  reinterpret_cast<CompiledMethod>(methodTrampoline6),
265  reinterpret_cast<CompiledMethod>(methodTrampoline7),
266  reinterpret_cast<CompiledMethod>(methodTrampoline8),
267  reinterpret_cast<CompiledMethod>(methodTrampoline9),
268  reinterpret_cast<CompiledMethod>(methodTrampoline10)
269 };
270 } // end anonymous namespace
271 
272 namespace Interpreter
273 {
278  reinterpret_cast<ClosureInvoke>(closureTrampoline0),
279  reinterpret_cast<ClosureInvoke>(closureTrampoline1),
280  reinterpret_cast<ClosureInvoke>(closureTrampoline2),
281  reinterpret_cast<ClosureInvoke>(closureTrampoline3),
282  reinterpret_cast<ClosureInvoke>(closureTrampoline4),
283  reinterpret_cast<ClosureInvoke>(closureTrampoline5),
284  reinterpret_cast<ClosureInvoke>(closureTrampoline6),
285  reinterpret_cast<ClosureInvoke>(closureTrampoline7),
286  reinterpret_cast<ClosureInvoke>(closureTrampoline8),
287  reinterpret_cast<ClosureInvoke>(closureTrampoline9),
288  reinterpret_cast<ClosureInvoke>(closureTrampoline10)
289 };
290 void Value::set(Obj o)
291 {
292  if (needsGC(object) && !needsGC(o))
293  {
294  assert(holder != nullptr);
295  GC_free(holder);
296  holder = nullptr;
297  }
298  else if (!needsGC(object) && needsGC(o))
299  {
300  assert(holder == nullptr);
301  // If we're wrapping an object that needs to be tracked by the GC, then
302  // we allocate a small buffer that is scanned by the GC, but not
303  // collected by it, to hold the value.
304  holder = reinterpret_cast<Obj*>(GC_malloc_uncollectable(sizeof(Obj)));
305  *holder = o;
306  }
307  else if (needsGC(object) && needsGC(o))
308  {
309  *holder = o;
310  }
311  object = o;
312 }
313 Value::~Value()
314 {
315  if (needsGC(object))
316  {
317  assert(holder != nullptr);
318  GC_free(holder);
319  }
320 }
321 Obj *Context::lookupSymbol(const std::string &name)
322 {
323  // If there's a symbol table stack, then look in the top one. We don't need
324  // to go deeper, because any bound variables should be added automatically
325  // to the top.
326  if (!symbols.empty())
327  {
328  auto top = symbols.back();
329  auto I = top->find(name);
330  if (I != top->end())
331  {
332  return I->second;
333  }
334  }
335  // If it's not local, then look in the global symbol table.
336  auto I = globalSymbols.find(name);
337  if (I != globalSymbols.end())
338  {
339  return I->second;
340  }
341  // It's not found, so return null.
342  return nullptr;
343 }
344 
345 void Context::setSymbol(const std::string &name, Obj val)
346 {
347  Obj *addr = lookupSymbol(name);
348  // If storage doesn't exist for this symbol, it's a global so
349  // allocate some storage for it.
350  if (!addr)
351  {
352  // Construct a new Value to gold the object.
353  globals.emplace_front(val);
354  // Get the address of the storage that we've allocated and store it in
355  // the symbol table
356  addr = globals.front().address();
357  globalSymbols[name] = addr;
358  }
359  else
360  {
361  *addr = val;
362  }
363 }
364 
365 void Context::setSymbol(const std::string &name, Obj *val)
366 {
367  (*symbols.back())[name] = val;
368 }
369 
370 } // namespace Interpreter
371 
373 // Interpreter methods on AST classes
375 
377 {
378  for (auto &s : statements)
379  {
380  // If we've executed a return statement, then stop executing.
381  if (c.isReturning)
382  {
383  return;
384  }
385  s->interpret(c);
386  }
387 }
388 
389 void Statements::collectVarUses(std::unordered_set<std::string> &decls,
390  std::unordered_set<std::string> &uses)
391 {
392  for (auto &s : statements)
393  {
394  s->collectVarUses(decls, uses);
395  }
396 }
397 
399 {
400  // If this is a constant expression and we've cached the value, then return
401  // the cached result.
402  if (cache)
403  {
404  return cache;
405  }
406  // Ask the subclass to evaluate the expression
407  Obj r = evaluateExpr(c);
408  // Cache it, if it's a constant expression
409  if (isConstantExpression())
410  {
411  cache = r;
412  }
413  return r;
414 }
415 
417 {
418  // Array of arguments.
419  Obj args[10];
420  // Get the callee, which is either a closure or some other object that will
421  // have a method on it invoked.
422  Obj obj = callee->evaluate(c);
423  assert(obj);
424  auto &argsAST = arguments->arguments;
425  size_t i=0;
426  // Evaluate each argument, in order, and pop them in the array.
427  for (auto &Arg : argsAST)
428  {
429  assert(i<(sizeof(args)/sizeof(Obj)));
430  args[i++] = Arg->evaluate(c);
431  }
432  // Get the class
433  currentContext = &c;
434  // If there's no method, then we're trying to invoke a closure.
435  if (!method)
436  {
437  assert(obj->isa == &ClosureClass);
438  Closure *closure = reinterpret_cast<Closure*>(obj);
439  return callCompiledClosure(closure->invoke, closure, args, i);
440  }
441  // Look up the selector and method to call
442  Selector sel = lookupSelector(*method.get());
443  assert(sel);
445  assert(mth);
446  // Call the method.
447  return callCompiledMethod(mth, obj, sel, args, arguments->arguments.size());
448 }
449 
451 {
452  // Get the address of the variable corresponding to this symbol and then
453  // load the object stored there.
454  return *c.lookupSymbol(name);
455 }
456 
457 void ClosureDecl::check()
458 {
459  // Don't do this if we've already done it.
460  if (checked)
461  {
462  return;
463  }
464  // Recursively collect all of the variables that are declared and referenced
465  // by statements in this closure.
466  body->collectVarUses(decls, boundVars);
467  // Parameters are not bound variables, they're explicitly passed in.
468  for (auto &param : parameters->arguments)
469  {
470  boundVars.erase(*param.get());
471  }
472  // Variables that are declared in this function are also not bound
473  // variables.
474  for (auto &decl : decls)
475  {
476  boundVars.erase(decl);
477  }
478  checked = true;
479 }
480 
481 void ClosureDecl::collectVarUses(std::unordered_set<std::string> &decls,
482  std::unordered_set<std::string> &uses)
483 {
484  // Find all of the variables that are used by this closure.
485  check();
486  // Add any bound variables to the use list
487  uses.insert(boundVars.begin(), boundVars.end());
488  // Add the name of this closure to the declared list in the enclosing scope.
489  decls.insert(name);
490 }
491 
493 {
494  check();
495  // Allocate the closure, with enough space for all of the bound variables
496  // at the end.
497  // Note that, in the current implementation, closures are always allocated
498  // on the heap. In many cases, closures do not persist longer than their
499  // wrapping function. In these cases, we could potentially allocate them
500  // on the stack, but making this determination requires a write barrier for
501  // the store.
502  Closure *C = gcAlloc<Closure>(boundVars.size() * sizeof(Obj));
503  // Set up the class pointer
504  C->isa = &ClosureClass;
505  // Set up the parameter count
506  size_t params = parameters->arguments.size();
507  C->parameters = createSmallInteger(params);
508  C->AST = this;
509  C->invoke = compiledClosure ? compiledClosure :
511  c.setSymbol(name, reinterpret_cast<Obj>(C));
512  int i=0;
513  // Copy bound variables into the closure.
514  for (auto &var : boundVars)
515  {
516  C->boundVars[i++] = *c.lookupSymbol(var);
517  }
518  return reinterpret_cast<Obj>(C);
519 }
520 
522  Selector sel, Obj *args)
523 {
524  check();
525  Class *cls = isInteger(self) ? &SmallIntClass : self->isa;
526  executionCount++;
527  // If we've interpreted this method enough times then try to compile it.
528  if (forceCompiler || (executionCount == compileThreshold))
529  {
530  mth->function = compileMethod(cls, c.globalSymbols);
531  compiledClosure = reinterpret_cast<ClosureInvoke>(mth->function);
532  }
533  // If we now have a compiled version, try to execute it.
534  if (compiledClosure)
535  {
536  return callCompiledMethod(reinterpret_cast<CompiledMethod>(compiledClosure),
537  self, sel, args, parameters->arguments.size());
538  }
539  // Create a new symbol table for this method.
540  Interpreter::SymbolTable closureSymbols;
541  c.pushSymbols(closureSymbols);
542  // Point the symbols for the arguments at our arguments array
543  size_t i=0;
544  for (auto &param : parameters->arguments)
545  {
546  c.setSymbol(*param.get(), &args[i++]);
547  }
548  Obj cmdObj = createSmallInteger(sel);
549  // Add self and cmd (receiver and selector) to the symbol table
550  c.setSymbol("self", &self);
551  c.setSymbol("cmd", &cmdObj);
552  // Add the addresses of the ivars in the self object to the symbol table.
553  Obj *ivars = (reinterpret_cast<Obj*>(&self->isa)) + 1;
554  for (int32_t i=0 ; i<cls->indexedIVarCount ; i++)
555  {
556  c.setSymbol(cls->indexedIVarNames[i], &ivars[i]);
557  }
558  // Interpret the statements in this method;
559  body->interpret(c);
560  // Return the return value. Make sure it's set back to nullptr after we've
561  // copied it so that we always return null from any method that doesn't
562  // explicitly return.
563  Obj retVal = c.retVal;
564  c.retVal = nullptr;
565  c.isReturning = false;
566  // Pop the symbols off the symbol table (very important, as they reference
567  // our stack frame!)
568  c.popSymbols();
569  return retVal;
570 }
572  Obj *args)
573 {
574  executionCount++;
575  // If we've interpreted this enough times, compile it.
576  if (forceCompiler || (executionCount == compileThreshold))
577  {
578  // Note that we don't pass any symbols other than the globals into the
579  // compiler, because all of the bound variables are already copied into
580  // the closure object when it is created.
581  self->invoke = compileClosure(c.globalSymbols);
582  compiledClosure = self->invoke;
583  }
584  // If we now have a compiled version, call it
585  if (compiledClosure)
586  {
587  return callCompiledClosure(compiledClosure, self, args,
588  parameters->arguments.size());
589  }
590  // Create a new symbol table for this closure
591  Interpreter::SymbolTable closureSymbols;
592  c.pushSymbols(closureSymbols);
593  size_t i=0;
594  // Add the parameters and the bound variables to the symbol table.
595  for (auto &param : parameters->arguments)
596  {
597  // Parameters are referenced from the arguments array
598  c.setSymbol(*param.get(), &args[i++]);
599  }
600  i = 0;
601  for (auto &bound : boundVars)
602  {
603  // Bound variables are stored within the closure object
604  c.setSymbol(bound, &self->boundVars[i++]);
605  }
606  // Interpret the body
607  body->interpret(c);
608  // Return the return value. Make sure it's set back to nullptr after we've
609  // copied it so that we always return null from any method that doesn't
610  // explicitly return.
611  Obj retVal = c.retVal;
612  c.retVal = nullptr;
613  c.isReturning = false;
614  // Pop the symbols off the symbol table (very important, as they reference
615  // our stack frame!)
616  c.popSymbols();
617  return retVal;
618 }
619 
621 {
622  // Construct a string object.
623  String *str = gcAlloc<String>(size());
624  assert(str != nullptr);
625  // Set the class pointer
626  str->isa = &StringClass;
627  // Set the length (as a small integer)
629  // Copy the characters into the object
630  copy(str->characters, size(), 0);
631  return reinterpret_cast<Obj>(str);
632 }
633 
635 {
636  if ((reinterpret_cast<intptr_t>(condition->evaluate(c))) & ~7)
637  {
638  body->interpret(c);
639  }
640 }
642 {
643  while (!c.isReturning && (reinterpret_cast<intptr_t>(condition->evaluate(c))) & ~7)
644  {
645  body->interpret(c);
646  }
647 }
649 {
650  // Declarations don't normally allocate space for variables, but at the
651  // global scope then storing null in a global will trigger its allocation.
652  Obj v = nullptr;
653  if (init)
654  {
655  v = init->evaluate(c);
656  }
657  c.setSymbol(name, v);
658 }
659 
661 {
662  c.setSymbol(target->name, expr->evaluate(c));
663 }
664 
666 {
667  Obj LHS = lhs->evaluate(c);
668  Obj RHS = rhs->evaluate(c);
669  // If this is a comparison, then we're doing a pointer-compare even if
670  // they're objects. If both sides are small integers, then ask the subclass
671  // to look up their integer values.
672  if (isComparison() || (isInteger(LHS) && isInteger(RHS)))
673  {
674  // Ask the subclass to evaluate the expression with integer arguments.
675  // Note that we can't use getInteger() here because the assert that this
676  // really is a small integer is not valid - if we're doing a comparison
677  // then the arguments might be pointers.
678  return createSmallInteger(evaluateWithIntegers(
679  (reinterpret_cast<intptr_t>(LHS)) >> 3,
680  (reinterpret_cast<intptr_t>(RHS)) >> 3));
681  }
682  Selector sel = lookupSelector(methodName());
684  // If this method calls back into the interpreter, then we must be able to
685  // find the context.
686  currentContext = &c;
687  return (reinterpret_cast<Obj(*)(Obj,Selector,Obj)>(mth))(LHS, sel, RHS);
688 }
689 
691 {
692  // Evaluate the returned expression and then indicate in the interpreter
693  // context that we're returning.
694  c.retVal = expr->evaluate(c);
695  c.isReturning = true;
696 }
697 
699 {
700  // Construct the new class. The class table persists over the lifetime of
701  // the program, so memory allocated here is never freed.
702  Class *cls = new Class();
703  // Due to the way automatic AST construction works, we'll end up with the
704  // class name in the superclass name field if we don't have a superclass.
705  std::string &clsName = name ? *name : superclassName;
706  cls->superclass = name ? lookupClass(superclassName) : nullptr;
707  cls->className = strdup(clsName.c_str());
708  cls->methodCount = methods.size();
709  if (cls->superclass)
710  {
712  }
713  cls->indexedIVarCount += ivars.size();
714  // Construct the method list, with one Method structure for the metadata for
715  // each method.
716  cls->methodList = new Method[cls->methodCount];
717  Method *method = cls->methodList;
718  for (auto &m : methods)
719  {
720  method->selector = lookupSelector(m->name);
721  method->args = m->parameters->arguments.size();
722  // Currently, we only have trampolines for up to 10 arguments. We could
723  // reuse some of the JIT code to generate new ones at run time if
724  // this were intended for production use, but this is okay as an
725  // example.
726  assert(method->args <= 10);
727  // Insert a trampoline for the method
728  method->function = methodTrampolines[method->args];
729  // We retain ownership of the AST node, but the method will contain a
730  // pointer to it.
731  method->AST = m.get();
732  method++;
733  }
734  // Set up the names of the instance variables.
735  cls->indexedIVarNames = new const char*[cls->indexedIVarCount];
736  const char **ivar = cls->indexedIVarNames;
737  // Copy superclass ivars.
738  if (cls->superclass != nullptr)
739  {
740  for (int i=0 ; i<cls->superclass->indexedIVarCount ; i++)
741  {
742  *(ivar++) = cls->superclass->indexedIVarNames[i];
743  }
744  }
745  for (auto &i : ivars)
746  {
747  *(ivar++) = strdup(i->name.c_str());
748  }
749  // Add the class to the class table.
750  registerClass(clsName, cls);
751 }
752 Obj NewExpr::evaluateExpr(Interpreter::Context &c)
753 {
754  // Look up the class in the class table and create a new instance of it.
755  return newObject(lookupClass(className));
756 }
757 
Obj closureTrampoline8(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6, Obj o7)
8-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:101
Obj closureTrampoline3(Closure *C, Obj o0, Obj o1, Obj o2)
3-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:54
void interpret(Interpreter::Context &c) override
Interpret the assignment, updating the stored value.
Definition: interpreter.cc:660
struct Class * isa
The pointer to the class of this object.
Definition: runtime.hh:150
Object *(* CompiledMethod)(Object *, Selector,...)
A compiled method is a function that takes an object (the receiver) and the selector as implicit argu...
Definition: runtime.hh:75
Obj methodTrampoline1(Obj self, Selector cmd, Obj o0)
1-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:142
Object * Obj
Object pointer.
Definition: runtime.hh:33
Obj closureTrampoline4(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3)
4-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:63
Obj callCompiledClosure(ClosureInvoke m, Closure *receiver, Obj *args, int argCount)
Calls a compiled closure from the specified argument list.
Definition: runtime.cc:656
Obj evaluateExpr(Interpreter::Context &c) override
Evaluate this by looking up the variable in the interpreter&#39;s symbol table and loading it...
Definition: interpreter.cc:450
Value retVal
The value currently being returned, if there is one.
Definition: interpreter.hh:128
CompiledMethod methodTrampolines[]
Array of trampolines, indexed by number or arguments.
Definition: interpreter.cc:257
uint32_t Selector
Selectors are unique identifiers for methods.
Definition: runtime.hh:70
AST::ClosureDecl * AST
The AST for this closure.
Definition: runtime.hh:217
void popSymbols()
Pop the top symbol table off the stack.
Definition: interpreter.hh:140
bool needsGC(Obj o)
Indicates whether a particular object needs to be visible to the GC.
Definition: interpreter.cc:16
const char ** indexedIVarNames
The names of the instance variables.
Definition: runtime.hh:136
void interpret(Interpreter::Context &c)
Interprets each of the statements in turn.
Definition: interpreter.cc:376
ClosureInvoke invoke
The function that is used to invoke this closure.
Definition: runtime.hh:213
Obj closureTrampoline9(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6, Obj o7, Obj o8)
9-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:111
Obj closureTrampoline2(Closure *C, Obj o0, Obj o1)
2-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:45
struct Class SmallIntClass
The SmallInt (Number) class structure.
Definition: runtime.cc:531
void interpret(Interpreter::Context &c) override
Sets the variable to the value in the initialisation.
Definition: interpreter.cc:648
Obj methodTrampoline4(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3)
4-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:175
std::unordered_map< std::string, Obj * > SymbolTable
A symbol table stores the address of each allocation.
Definition: interpreter.hh:103
Obj methodTrampoline8(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6, Obj o7)
8-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:222
Class * isa
Class pointer.
Definition: runtime.hh:184
Obj evaluateExpr(Interpreter::Context &c) override
Evaluate the.
Definition: interpreter.cc:620
struct Method * methodList
An array of methodCount elements describing the methods that this class implements.
Definition: runtime.hh:132
Obj evaluateExpr(Interpreter::Context &c) override
Call the relevant method or closure.
Definition: interpreter.cc:416
Selector lookupSelector(const std::string &str)
Looks up the selector for a specified string value, registering a new value if this is the first time...
Definition: runtime.cc:553
Interpreter::Context * currentContext
Definition: interpreter.cc:21
Obj newObject(struct Class *cls)
Instantiate an object.
Definition: runtime.cc:606
Object *(* ClosureInvoke)(Closure *,...)
A compiled closure invoke function.
Definition: runtime.hh:80
Obj methodTrampoline7(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6)
7-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:210
Obj boundVars[0]
An array of bound variables in this closure.
Definition: runtime.hh:221
void registerClass(const std::string &name, struct Class *cls)
Register a newly constructed class.
Definition: runtime.cc:596
Obj closureTrampoline1(Closure *C, Obj o0)
1-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:36
void interpret(Interpreter::Context &c) override
Interpret, but constructing the class.
Definition: interpreter.cc:698
Obj evaluate(Interpreter::Context &c)
Evaluate the expression, caching the result if it&#39;s a constant expression.
Definition: interpreter.cc:398
struct Class * lookupClass(const std::string &name)
Look up an existing class.
Definition: runtime.cc:601
Obj interpretClosure(Interpreter::Context &c, MysoreScript::Closure *self, Obj *args)
Interprets the closure in the current context.
Definition: interpreter.cc:571
A generic MysoreScript object.
Definition: runtime.hh:144
Obj evaluateExpr(Interpreter::Context &c) override
Evaluates the expression, either invoking a subclass evaluateWithIntegers method or by calling the re...
Definition: interpreter.cc:665
Obj * lookupSymbol(const std::string &name)
Look up a symbol, walking up the symbol table stack until it&#39;s found.
Definition: interpreter.cc:321
AST::ClosureDecl * AST
The AST for this method.
Definition: runtime.hh:102
bool isReturning
Are we currently returning?
Definition: interpreter.hh:132
bool forceCompiler
Force the compiler to run.
Definition: interpreter.cc:7
Obj methodTrampoline5(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4)
5-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:186
int32_t args
The number of arguments that this method takes.
Definition: runtime.hh:94
struct Class StringClass
The String class structure.
Definition: runtime.cc:492
struct Class ClosureClass
The Closure class structure.
Definition: runtime.cc:543
Obj methodTrampoline6(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5)
6-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:198
Obj methodTrampoline3(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2)
3-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:164
ClosureInvoke closureTrampolines[]
Array of trampolines, indexed by number or arguments.
Definition: interpreter.cc:277
CompiledMethod function
The compiled method, if one exists.
Definition: runtime.hh:98
Obj methodTrampoline10(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6, Obj o7, Obj o8, Obj o9)
10-argument trampoline for jumping back into the interpreter when a method that has not yet been comp...
Definition: interpreter.cc:246
Method * methodForSelector(Class *cls, Selector sel)
Looks up the Method that should be invoked for the specified selector on this class.
Definition: runtime.cc:615
Obj evaluateExpr(Interpreter::Context &c) override
Evaluate this closure, returning the closure object representing it.
Definition: interpreter.cc:492
void setSymbol(const std::string &name, Obj *val)
Set the address where the variable corresponding to a particular symbol is stored.
CompiledMethod compiledMethodForSelector(Obj obj, Selector sel)
Look up the compiled method to call for a specific selector.
Definition: runtime.cc:697
Class * isa
Class pointer.
Definition: runtime.hh:204
Obj interpretMethod(Interpreter::Context &c, MysoreScript::Method *mth, Obj self, MysoreScript::Selector sel, Obj *args)
Interprets the closure, assuming that it is a method.
Definition: interpreter.cc:521
Obj closureTrampoline7(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6)
7-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:91
Obj callCompiledMethod(CompiledMethod m, Obj receiver, Selector sel, Obj *args, int argCount)
Calls a compiled method, constructing the correct argument frame based on the arguments.
Definition: runtime.cc:632
char characters[0]
An array of characters.
Definition: runtime.hh:193
struct Class * superclass
The superclass of this class, if it has one, or a null pointer if it is a root class.
Definition: runtime.hh:115
void interpret(Interpreter::Context &c) override
Interpret the returned expression and then indicate in the context that we have hit a return statemen...
Definition: interpreter.cc:690
Obj closureTrampoline10(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6, Obj o7, Obj o8, Obj o9)
10-argument trampoline for jumping back into the interpreter when a closure that has not yet been com...
Definition: interpreter.cc:121
int32_t methodCount
The number of methods that this class implements.
Definition: runtime.hh:123
The primitive String class in MysoreScript.
Definition: runtime.hh:179
int32_t indexedIVarCount
The number of indexed instance variables that this class has.
Definition: runtime.hh:127
void interpret(Interpreter::Context &c) override
Interpret the condition, then interpret the body if the condition is true.
Definition: interpreter.cc:634
Obj methodTrampoline2(Obj self, Selector cmd, Obj o0, Obj o1)
2-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:153
Obj closureTrampoline6(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5)
6-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:81
Definition: ast.hh:17
const char * className
The name of this class.
Definition: runtime.hh:119
Obj createSmallInteger(intptr_t i)
Construct a small integer object from the given integer.
Definition: runtime.hh:59
void collectVarUses(std::unordered_set< std::string > &decls, std::unordered_set< std::string > &uses)
Visits each statement to collect its variable uses and definitions.
Definition: interpreter.cc:389
Obj closureTrampoline5(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4)
5-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:72
void interpret(Interpreter::Context &c) override
Interpret the body as long as the condition remains true.
Definition: interpreter.cc:641
void pushSymbols(SymbolTable &s)
Push a new symbol table on top of the stack.
Definition: interpreter.hh:136
Obj methodTrampoline9(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, Obj o5, Obj o6, Obj o7, Obj o8)
9-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:234
Obj length
The number of characters in the string.
Definition: runtime.hh:188
Struct holding metadata about a class.
Definition: runtime.hh:109
Methods in a class&#39;s method list.
Definition: runtime.hh:85
SymbolTable globalSymbols
Global symbols.
Definition: interpreter.hh:121
Obj closureTrampoline0(Closure *C)
0-argument trampoline for jumping back into the interpreter when a closure that has not yet been comp...
Definition: interpreter.cc:28
bool isInteger(Obj o)
Is this object a small integer (lowest bit is 1, next two bits are 0).
Definition: runtime.hh:43
Obj parameters
The number of parameters that this object has.
Definition: runtime.hh:208
Obj methodTrampoline0(Obj self, Selector cmd)
0-argument trampoline for jumping back into the interpreter when a method that has not yet been compi...
Definition: interpreter.cc:132
The layout of all closures in MysoreScript.
Definition: runtime.hh:199
Selector selector
The selector that this method applies to.
Definition: runtime.hh:90