String[] vars = getVars(alt, altTag);
Map<QualifiedName, Integer> newEnv = argOffset (0, p);
for (int j = 0; j < vars.length; ++j) {
QualifiedName qn = QualifiedName.make(moduleName, vars [j]);
newEnv.put (qn, Integer.valueOf(d + 1 + j));
}
// i_split: takes a dc object, tells it to push all (vars.length) fields onto the stack
InstructionList altGP = new InstructionList ();
altGP.code (new Instruction.I_Split (vars.length));
altGP.code (schemeR(alt.getAltExpr(), newEnv, d + vars.length));
Code code = new Code(altGP);
altTagToCodeMap.put(altTag, code);
}
}
ErrorInfo errorInfo = sw.getErrorInfo() == null ? null : toRuntimeErrorInfo(sw.getErrorInfo());
gp.code (new Instruction.I_Switch (altTagToCodeMap, errorInfo));
return gp;
}
// Is e a data constructor field selection?
Expression.DataConsSelection dataConsSelection = e.asDataConsSelection();
if (dataConsSelection != null) {
if (CODEGEN_DIAG) {
MACHINE_LOGGER.log(Level.FINE, " selectDC:");
}
gp.code (schemeC(dataConsSelection.getDCValueExpr(), p, d));
gp.code (new Instruction.I_LazySelectDCField(dataConsSelection.getDataConstructor(),
dataConsSelection.getFieldIndex(),
toRuntimeErrorInfo (dataConsSelection.getErrorInfo())));
// // Evaluate the code for the dc-valued expr.
//gp.code (schemeE (dataConsSelection.getDCValueExpr(), p, d));
// // Extract the field value onto the stack.
// int fieldIndex = dataConsSelection.getFieldIndex();
// ErrorInfo errorInfo = dataConsSelection.getErrorInfo() == null ? null : new ErrorInfo(dataConsSelection.getErrorInfo());
// gp.code (new Instruction.I_SelectDCField (dataConsSelection.getDataConstructor(), fieldIndex, errorInfo));
// // Add a var to the env, and generate code for that var.
// Expression.Var varName = dataConsSelection.getVarName();
// QualifiedName varQualifiedName = varName.getName();
// Map newEnv = argOffset (0, p);
// newEnv.put (varQualifiedName, JavaPrimitives.makeInteger (d + 1));
// gp.code (schemeR(varName, newEnv, d + 1));
appendUpdateCode (gp, d);
return gp;
}
// Is e a let expression?
Expression.Let let = e.asLet();
if (let != null) {
// Currently the compiler doesn't differentialte between let and letrec scenarios.
// As such we have to treat all lets as letrecs.
Expression.Let.LetDefn[] defs = let.getDefns();
EnvAndDepth ead = schemeXr (defs, p, d);
InstructionList gprecs = schemeCLetrec (defs, ead.env, ead.depth);
gp.code (gprecs);
gp.code (schemeR (let.getBody (), ead.env, ead.depth));
return gp;
}
// Is e a tail recursive call?
if (e.asTailRecursiveCall() != null) {
// The g-machine doesn't have a specific optimization for tail recursive calls
// so we simply handle it as the original fully saturated application and let
// the general tail call optimization handle it.
return schemeR (e.asTailRecursiveCall().getApplForm(), p, d);
}
// Is e an application?
Expression.Appl appl = e.asAppl();
if (appl != null) {
if (CODEGEN_DIAG) {
MACHINE_LOGGER.log(Level.FINE, " Application:");
}
InstructionList il = schemeRS (e, p, d, 0);
if (il != null) {
gp.code (il);
return gp;
}
gp.code (schemeC (e, p, d));
appendUpdateCode(gp, d);
return gp;
}
// Is e a record update
// e is a record update
Expression.RecordUpdate recordUpdate = e.asRecordUpdate();
if (recordUpdate != null) {
if (CODEGEN_DIAG) {
MACHINE_LOGGER.log(Level.FINE, " Record update:");
}
gp.code (schemeE (e, p, d));
appendUpdateCode (gp, d);
return gp;
}
// Is e a record extension
// e is a record extension
Expression.RecordExtension recordExtension = e.asRecordExtension();
if (recordExtension != null) {
if (CODEGEN_DIAG) {
MACHINE_LOGGER.log(Level.FINE, " Record extension:");
}
gp.code (schemeE (e, p, d));
appendUpdateCode (gp, d);
return gp;
}
// e is a record selection
Expression.RecordSelection recordSelection = e.asRecordSelection();
if (recordSelection != null) {
if (CODEGEN_DIAG) {
MACHINE_LOGGER.log(Level.FINE, " Record selection:");
}
gp.code (schemeE (e, p, d));
appendUpdateCode (gp, d);
return gp;
}
// e is a record case
Expression.RecordCase recordCase = e.asRecordCase();
if (recordCase != null) {
// Strictly compile the condition expression
Expression conditionExpr = recordCase.getConditionExpr();
gp.code (schemeE (conditionExpr, p, d));
Map<QualifiedName, Integer> newEnv = argOffset (0, p);
QualifiedName recordName = QualifiedName.make(currentMachineFunction.getQualifiedName().getModuleName(), "$recordCase");
newEnv.put (recordName, Integer.valueOf(++d));
//FieldName -> String
SortedMap<FieldName, String> fieldBindingVarMap = recordCase.getFieldBindingVarMap();
int recordPos = 0;
// This creates, if necessary, a record equivalent to the original record minus the bound fields.
String baseRecordPatternVarName = recordCase.getBaseRecordPatternVarName();
if (baseRecordPatternVarName != null &&
!baseRecordPatternVarName.equals(Expression.RecordCase.WILDCARD_VAR)) {
recordPos++;
// Create a new record that is the original record minus the bound fields.
QualifiedName qn = QualifiedName.make(currentMachineFunction.getQualifiedName().getModuleName(), baseRecordPatternVarName);
newEnv.put (qn, Integer.valueOf(++d));
// push the original record
gp.code (new Instruction.I_Push(0));
// consume the record on top of the stack and replace with an extended version
gp.code (new Instruction.I_ExtendRecord());
// Now remove fields from the record as appropriate.
for (final FieldName fieldName : fieldBindingVarMap.keySet()) {
gp.code (new Instruction.I_RemoveRecordField(fieldName.getCalSourceForm()));
}
}
// Now push the values for the bound fields onto the stack.
for (final Map.Entry<FieldName, String> entry : fieldBindingVarMap.entrySet()) {
FieldName fieldName = entry.getKey();
String bindingVarName = entry.getValue();
//ignore anonymous pattern variables. These are guaranteed not to be used
//by the result expression, and so don't need to be extracted from the condition record.
if (!bindingVarName.equals(Expression.RecordCase.WILDCARD_VAR)) {
QualifiedName qn = QualifiedName.make(currentMachineFunction.getQualifiedName().getModuleName(), bindingVarName);
newEnv.put(qn, Integer.valueOf(++d));
gp.code (new Instruction.I_Push (recordPos));
gp.code (new Instruction.I_RecordSelection (fieldName.getCalSourceForm()));
recordPos++;