package org.simantics.scl.compiler.internal.deriving; import java.util.ArrayList; import org.simantics.scl.compiler.common.datatypes.Constructor; import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.constants.StringConstant; import org.simantics.scl.compiler.elaboration.errors.NotPatternException; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EConstant; import org.simantics.scl.compiler.elaboration.expressions.EListLiteral; import org.simantics.scl.compiler.elaboration.expressions.ELiteral; import org.simantics.scl.compiler.elaboration.expressions.ERecord; import org.simantics.scl.compiler.elaboration.expressions.EVar; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.elaboration.modules.TypeAlias; import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; import org.simantics.scl.compiler.environment.AmbiguousNameException; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.environment.Environments; import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst; import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst; import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst; import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst; import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository; import org.simantics.scl.compiler.internal.parsing.types.TVarAst; import org.simantics.scl.compiler.types.TApply; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; class JsonDeriver implements InstanceDeriver { @Override public void derive( ErrorLog errorLog, Environment environment, ArrayList instancesAst, DDerivingInstanceAst der) { // Analyze if(der.types.length != 1) { errorLog.log(der.location, "Invalid number of parameters to " + der.name); return; } TVarAst headType = DerivingUtils.getHeadType(der.types[0]); if(headType == null) { errorLog.log(der.types[0].location, "Cannot derive Json instance for the type " + headType + "."); return; } TCon con; try { con = Environments.getTypeDescriptorName(environment, headType.name); } catch (AmbiguousNameException e1) { errorLog.log(headType.location, e1.getMessage()); return; } if(con == null) { errorLog.log(headType.location, "Couldn't resolve " + headType.name); return; } TypeDescriptor tdesc = environment.getTypeDescriptor(con); if(tdesc == null) { errorLog.log(headType.location, "Didn't find type constructor for " + headType.name); return; } if(tdesc instanceof TypeAlias) { errorLog.log(headType.location, "Cannot derive instance for a type alias."); return; } TypeConstructor tcon = (TypeConstructor)tdesc; if(tcon.isOpen) { errorLog.log(headType.location, "Cannot derive instance for open data types."); return; } if(tcon.constructors.length != 1) { errorLog.log(headType.location, "Data must have exactly one constructor for deriving to work."); return; } Constructor constructor = tcon.constructors[0]; if(constructor.recordFieldNames == null) { errorLog.log(headType.location, "Data must have a record constructor for deriving to work."); return; } DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types); ValueRepository valueDefs = new ValueRepository(); SCLValue fromJson = environment.getValue(Names.Json_fromJson); SCLValue toJson = environment.getValue(Names.Json_toJson); SCLValue lookupJsonField = environment.getValue(Names.Json_lookupJsonField); SCLValue JsonObject = environment.getValue(Names.Json_JsonObject); SCLValue JsonField = environment.getValue(Names.Json_JsonField); SCLValue Just = environment.getValue(Names.Builtin_Just); SCLValue fromJust = environment.getValue(Names.Prelude_fromJust); SCLValue map = environment.getValue(Names.Prelude_map); SCLValue filterJust = environment.getValue(Names.Prelude_filterJust); SCLValue dot = environment.getValue(Names.Prelude_dot); // Collect all relevant information about the constructor String constructorName = constructor.name.name; int fieldCount = constructor.parameterTypes.length; String[] fieldNames = constructor.recordFieldNames; boolean[] isOptional = new boolean[fieldCount]; boolean hasAtLeastOneOptional = false; for(int i=0;i