Skip to content

How to Avoid Breaking the Rascal Bootstrap

Paul Klint edited this page Feb 24, 2017 · 27 revisions

We are currently at the brink of switching to a development cycle where we critically depend on previously compiled code (e.g. Kernel, ParserGenerator). This page is intended to get an overall picture of changes which break compatibility of the language and/or the runtime. Either the automated bootstrap process can cater for such breaking changes, or it can not. In the latter case we explain how to workaround the issue manually.

Please:

  • Add missing scenarios
  • Correct scenarios
  • Add validation per scenario (how has this scenario been tested?)

Scenarios that will break the bootstrap

✔️ means we validated the scenario indeed breaks the bootstrap and we need a workaround

  • Make any test fail *

Any failing test will make the bootstrap halt. There is no other way then to fix the bug or adapt the test such that it makes sense again.

  • Remove a Rascal language feature which is used by the compiler or type checker code itself

That is just not possible. You have to first rewrite the source code of the compiler to avoid using the deprecated feature. The previous compiler will not help of course, so it would be good to introduce first an analysis to the type checker to mark the deprecated feature. That way you and other users can be helped by the IDE to remove the old feature before it becomes unsupported.

  • Changing parameters of commandline tools rascalc, compileMuLibrary

Since the Bootstrap script depends on these parameters, and it calls both the previous versions from the jar and the new versions in the bin folder, the commandline parameters must never change without an intermediate step.

Workaround:

  1. Support transition in Bootstrap script by case distinction of phase 1 and phase 2 (to use old parameters) and phase 3 and phase 4 to use the new parameters.
  2. Bootstrap and release
  3. Change Bootstrap script to remove case distinctions
  4. Bootstrap and release
  • Changing parameters of the Kernel function compile without leaving the older version in tact.

We need the old version of the compile function at least a while longer to be able to run the tests of phase 1 and to start phase 2 of the bootstrap process. The reason is that the new compiler with the new compile signature will be combined using an older jar folder with the RVM which includes an older version of the RascalC command which still hardwires the old signature of compile.

Workaround:

  1. One can use a keyword parameter to change the signature rather than a real parameter, or:
  2. Leave the old definition in and mark it deprecated.
  3. Bootstrap and release
  4. Remove the old definition
  5. Bootstrap again
  • Rename a class name in a vital library like org.rascalmpl.values (now io.usethesource.vallang)

It looks so simple, renaming a class name using an Eclipse refactoring. Unfortunately, life is less simple since the old class name may occur in string templates or generated byte code.

Before you decide to rename:

  1. Convince yourself that the renaming is really necessary.
  2. Search the Rascal code base (*.java,*.src,*.xml) for the old name and watch out for occurrences in
    • BytecodeGenerator
    • String templates
    • Configuration files
  3. Be aware of test data that may be affected.

Workarounds:

  1. Perform renamings in small steps and test and bootstrap in between, this will expose problems as soon as possible.
  2. If the renamed class names can occur in generated byte code, activate the class renaming in Execute.rsc. and make sure in Bootstrap.java that old and new names are both available during compilation.

Here is a list of dangerous names that require special attention when renamed.

Used by BytecodeGenerator:

  • io.usethesource.vallang.type.Type
  • IValue
  • IValueFactory
  • IString
  • IBool
  • IList
  • IInteger
  • ISet
  • IMap
  • ITuple
  • RVMExecutable
  • RascalExecutionContext
  • RVMonJVM
  • Frame
  • Function
  • RascalPrimitive
  • MuPrimitive
  • Reference
  • Coroutine
  • Thrown

Generated by parsergenerator:

  • io.usethesource.vallang.type.TypeFactory
  • io.usethesource.vallang.IConstructor
  • io.usethesource.vallang.ISourceLocation
  • io.usethesource.vallang.IValue
  • io.usethesource.vallang.IValueFactory
  • io.usethesource.vallang.exceptions.FactTypeUseException
  • `io.usethesource.vallang.io.StandardTextReader
  • org.rascalmpl.parser.gtd.stack.*
  • org.rascalmpl.parser.gtd.stack.filter.*
  • org.rascalmpl.parser.gtd.stack.filter.follow.*
  • org.rascalmpl.parser.gtd.stack.filter.match.*
  • org.rascalmpl.parser.gtd.stack.filter.precede.*
  • org.rascalmpl.parser.gtd.preprocessing.ExpectBuilder
  • org.rascalmpl.parser.gtd.util.IntegerKeyedHashMap
  • org.rascalmpl.parser.gtd.util.IntegerList
  • org.rascalmpl.parser.gtd.util.IntegerMap
  • org.rascalmpl.values.ValueFactoryFactory
  • org.rascalmpl.values.uptr.RascalValueFactory
  • org.rascalmpl.values.uptr.ITree

Scenarios that do not break the bootstrap:

✔️ means we tested this scenario and indeed the bootstrap script will work around a language-breaking or virtual machine-breaking change by using the previously released version of the Rascal compiler:

  • renaming a MuPrimitive; ok if you change the compiler to generate the new name and the MuPrimitive name as well
  • renaming a RascalPrimitive;
  • changing the signature of a MuPrimitive
  • changing the signature of a RascalPrimitive
  • Changing Rascal functions other than Kernel functions
  • Changing Java code that is unrelated to serialization
  • Adding a Rascal language feature (e.g. coroutines) Note: any changes to the existing implementation should be handled according to the above approaches.
  • Changing IValue or Type internally, i.e. no API changes
  • Adding new IValues or Types
  • Change signature of Kernel function rascalTests
  • Adding field to a serialized Java class, e.g. RVMExecutable
  • Delete a field from a serialized class
  • Changing name or signature of Kernel function compile or compileAndLink
  • Change a constructor in the RVM datatype
  • Switching to automatic compression: |compressed+file:///.../Fac.rvm.ser.gz| to |file:///.../Fac.rvm.ser.gz|
  • Switching serialization format
  • Moving the compiler sources to another location
  • Removing a Rascal language feature which is not used by the compiler or any of the tests