Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated to match requiredEvaluation feature of current code base.

...

You can ask an OOLAGValue for its 'value', to get the ordinary value, but this will throw if there is no such value. Often one wants to call 'isError' first to decide if you want the value, but sometimes the throw is fine. E.g., if computing another attribute in terms of an attribute that has no value due to an error, the right behavior may be for this new attribute to also be in error state. If so, then no test for isError is required. The throw will cause the new attribute to also be in error. The OOLAG framework makes sure that there is no additional error/diagnostic recorded in this case.

OOLAG Hosts and Multiple Diagnostic Messages -

...

RequiredEvaluations

When compiling, we very often want to get more than one error message out. We don't want our compiler to fail on the very first problem as this leads to long debug cycles, and sometimes one can only figure out what is really wrong by looking at several errors at once.

...

The way this is done is that an OOLAGHost object is required to create a very critical member named diagnosticChildren. An OOLAGHost object answers isError with true if any of its diagnosticChildren answer isError with truecarries required evaluations. Each one of these method calls (which are lazy - the args aren't evaluated right away) indicates that for this OOLAGHost object to be considered to be without error, all these evaluations must take place, and not cause errors. The calculation is structured so that it does not stop on the first one that answers isError with truethrows or causes an error, but evaluates isError for all of them. The diagnostic objects for an OOLAGHost are the union of all the diagnostic objects for all its diagnosticChildren.One further detail. An OOLAGHost can also have local calculations. These also must be without error if isError is to return true, and any diagnostic objects created must be captured. The idiom here is that this is done using OOLAGValue calculations to compute all local attributes, and adding these OOLAGValue objects to the list of diagnosticChildren.

Example:

abstract class ElementBase(...) extends OOLAGHost { 

requiredEvaluations(typeDef)
requiredEvaluations(isSimpleType)
requiredEvaluations(if (hasPattern) patternValues)
requiredEvaluations(if (hasEnumeration) enumerationValues)

lazy val typeDef = typeDef_.value
private lazy val typeDef_ = LV { // object LV constructs an OOLAGValue
.... compute the type definition ....
}  lazy val diagnosticChildren = List(child1, child2, typeDef_ )

}

In the above, you see the two lines associated with the typeDef attribute of ElementBase. The first obtains the value, if possible from the LV (lazy value) created by the associated private typeDef_. This is the common idiom, to have two lines together like this.

...

I'm open to suggestions though. If some very very clever Scala technique can be used to improve this coding idiom, I'm all for it.

...

.

A Few Details

About warnings. The test 'isError' can be false, and an ordinary value be produced, but warnings may still have been accumulated. Hence, one can have diagnostic objects which represent warnings even when there is no error that stops processing.

...

  • OOLAG is a compiler-writers pattern
  • It requires functional programming to avoid the need for organizing code into passes
  • It requires use of special value objects that allow an ordinary value, a set of error/diagnostic objects, or both to be the "answer" of a calculation.
    • Every such value object can answer the 'isError' test.
  • Code is structured into OOLAGValue calculations (using the LV idiom) and OOLAGHost objects

    The list diagnosticChildren is central to the idiom

  •  OOLAGHost objects carry required evaluations that must be evaluated to insure they are 'done'